project-tiny-context-harness 0.7.8 → 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 -375
  3. package/assets/README.md +567 -552
  4. package/assets/README.zh-CN.md +339 -321
  5. package/assets/agents/.gitkeep +1 -1
  6. package/assets/agents/AGENTS_CORE.md +66 -58
  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 -112
  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 -87
  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 -103
  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
@@ -0,0 +1,74 @@
1
+ export function authorityRevisionDecisionNextAction(decision) {
2
+ const brief = decision.decision_brief;
3
+ const outcomes = brief.affected_outcomes.length
4
+ ? brief.affected_outcomes.join(", ")
5
+ : "contract-wide or global authority";
6
+ if (!decision.user_decision_required)
7
+ return `Authority Revision brief: ${brief.overview} ${brief.headline} ${brief.approval_reason} Material changes: ${brief.material_changes.join(" ")} Affected Outcomes: ${outcomes}. ${brief.if_approved.join(" ")}`;
8
+ return `Authority Revision brief: ${brief.overview} ${brief.headline} ${brief.approval_reason} Material changes: ${brief.material_changes.join(" ")} Affected Outcomes: ${outcomes}. ${brief.if_approved.join(" ")} Present this brief first. If an explicit task-specific user instruction already covers every listed decision reason, mechanically relay that existing decision for exact Authority Revision ${decision.revision_identity} without asking again. A generic continue, blanket approval, recommendation or Agent inference does not count. Otherwise ask the user once to approve or reject this exact identity; keep the previous Authority active until approved and atomically adopted.`;
9
+ }
10
+ export function buildAuthorityRevisionDecisionBrief(summary, changeClass, approvalRequired) {
11
+ const categories = [];
12
+ const materialChanges = [];
13
+ addCategory(summary.product_semantics_changed, "product meaning", detail("Product Claims or semantics changed", summary.product_claim_changes));
14
+ addCategory(summary.global_or_technical_semantics_changed, "technical meaning", detail("Global or technical semantics changed", summary.semantic_fields_changed));
15
+ addCategory(summary.source_or_claims_changed, "Source/Claims", detail("Source or Claim authority changed", summary.source_claim_changes));
16
+ addCategory(summary.context_authority_changed, "Context authority", "Controlling Context authority changed.");
17
+ addCategory(summary.acceptance_or_proof_weakened, "acceptance/proof", detail("Acceptance or proof was reduced", summary.proof_reductions));
18
+ addCategory(summary.verifier_or_runner_changed, "verifier/runner", "Verifier or runner authority changed.");
19
+ addCategory(summary.write_scope_expanded, "write scope", detail("Owner or allowed write scope expanded", uniqueSorted([
20
+ ...summary.expanded_owner_paths,
21
+ ...summary.expanded_expected_change_paths,
22
+ ...summary.expanded_allowed_support_paths,
23
+ ])));
24
+ addCategory(summary.risk_changed, "risk", "The effective risk authority changed.");
25
+ addCategory(summary.external_confirmations_changed, "external confirmations", detail("External-confirmation authority changed", summary.external_confirmation_changes));
26
+ if (summary.added_verification_dependencies.length)
27
+ materialChanges.push(detail("Verification dependencies were added", summary.added_verification_dependencies));
28
+ if (!materialChanges.length)
29
+ materialChanges.push(detail("Protected authority fields changed", summary.protected_reasons));
30
+ return {
31
+ overview: "An Authority Revision is a proposed replacement of the locked delivery contract or its protected inputs. It changes what future execution and proof are bound to, but adoption never completes delivery.",
32
+ headline: approvalRequired
33
+ ? `User decision required: ${categories.length ? categories.join(", ") : changeClass} changed.`
34
+ : "No user decision is required for this mechanically bounded Authority Revision.",
35
+ approval_reason: approvalRequired
36
+ ? changeClass === "scope_only_expansion"
37
+ ? "The candidate expands declared implementation ownership or write scope and cannot replace the active Authority without exact user approval."
38
+ : "The candidate changes protected delivery meaning, proof, risk, or execution authority and cannot replace the active Authority without exact user approval."
39
+ : changeClass === "scope_only_expansion"
40
+ ? "The candidate only expands repository-bound implementation scope; it changes no locked product Claim, target, acceptance capability, forbidden boundary or external confirmation."
41
+ : changeClass === "mechanically_bounded_repair"
42
+ ? "The locked user-facing meaning and proof obligations are preserved; changed execution, Source/Context snapshot or equivalent failure interception must still be re-proven on the new snapshot."
43
+ : "The change is a machine-proven monotonic strengthening.",
44
+ material_changes: materialChanges,
45
+ affected_outcomes: [...summary.affected_outcomes],
46
+ if_approved: approvalRequired
47
+ ? [
48
+ "The previous Authority remains active until exact approval and atomic adoption.",
49
+ "Approval and adoption do not complete delivery; execution returns to rolling implementation or repair.",
50
+ "A complete source-recompiled current-snapshot Final Gate remains mandatory.",
51
+ ]
52
+ : [
53
+ "The mechanically safe revision may be atomically adopted without user approval.",
54
+ "Adoption does not complete delivery; execution returns to rolling implementation or repair.",
55
+ "A complete source-recompiled current-snapshot Final Gate remains mandatory.",
56
+ ],
57
+ };
58
+ function addCategory(applies, category, materialChange) {
59
+ if (!applies)
60
+ return;
61
+ categories.push(category);
62
+ materialChanges.push(materialChange);
63
+ }
64
+ }
65
+ function detail(label, values) {
66
+ if (!values.length)
67
+ return `${label}.`;
68
+ const shown = values.slice(0, 3);
69
+ const remaining = values.length - shown.length;
70
+ return `${label}: ${shown.join(", ")}${remaining ? ` (+${remaining} more)` : ""}.`;
71
+ }
72
+ function uniqueSorted(values) {
73
+ return [...new Set(values)].sort((left, right) => left.localeCompare(right));
74
+ }
@@ -137,29 +137,29 @@ export function rollbackReductions(before, after) {
137
137
  : [];
138
138
  }
139
139
  export function counterfactualReductions(before, after) {
140
- const next = new Map(after.acceptance.counterfactual_controls.map((control) => [
141
- control.key,
142
- control,
143
- ]));
140
+ const next = after.acceptance.counterfactual_controls;
144
141
  return before.acceptance.counterfactual_controls
145
- .filter((control) => {
146
- const candidate = next.get(control.key);
147
- return !candidate || !same(control, candidate);
148
- })
142
+ .filter((control) => !counterfactualCoveragePreserved(control, next))
149
143
  .map((control) => `${after.key}:${control.key}`);
150
144
  }
151
145
  export function globalCounterfactualReductions(before, after) {
152
- const next = new Map(after.global.acceptance.counterfactual_controls.map((control) => [
153
- control.key,
154
- control,
155
- ]));
146
+ const next = after.global.acceptance.counterfactual_controls;
156
147
  return (before.global.acceptance.counterfactual_controls ?? [])
157
- .filter((control) => {
158
- const candidate = next.get(control.key);
159
- return !candidate || !same(control, candidate);
160
- })
148
+ .filter((control) => !counterfactualCoveragePreserved(control, next))
161
149
  .map((control) => `GLOBAL:${control.key}`);
162
150
  }
151
+ function counterfactualCoveragePreserved(previous, next) {
152
+ return next.some((candidate) => same(candidate.binding_key, previous.binding_key) &&
153
+ same(candidate.binding_ref, previous.binding_ref) &&
154
+ candidate.check_key === previous.check_key &&
155
+ same(candidate.mutation, previous.mutation) &&
156
+ includesEvery(candidate.claims, previous.claims) &&
157
+ includesEvery(candidate.expected_assertion_failures, previous.expected_assertion_failures));
158
+ }
159
+ function includesEvery(values, required) {
160
+ const available = new Set(values);
161
+ return required.every((value) => available.has(value));
162
+ }
163
163
  export function expandedPatterns(label, before, after) {
164
164
  return after
165
165
  .filter((candidate) => !before.some((existing) => proveRepositoryPatternSubset(candidate, existing).status ===
@@ -2,7 +2,7 @@ import type { CheckExecutionResultV2, LongTaskFindingV2 } from "./long-task-deli
2
2
  import type { AuthorityRevisionDecisionV2 } from "./long-task-authority-revision-types.js";
3
3
  export interface AuthorityRevisionDiagnosisV2 {
4
4
  schema_version: "long-task-authority-revision-diagnosis-v2";
5
- status: "no_authority_change" | "monotonic_revision_available" | "scope_candidate_exercised" | "scope_candidate_previewed" | "protected_change_previewed" | "candidate_stale";
5
+ status: "no_authority_change" | "monotonic_revision_available" | "automatic_revision_available" | "scope_candidate_exercised" | "scope_candidate_previewed" | "protected_change_previewed" | "candidate_stale";
6
6
  active_compiled_identity: string;
7
7
  candidate_compiled_identity: string;
8
8
  revision: AuthorityRevisionDecisionV2 | null;
@@ -48,6 +48,14 @@ export async function diagnoseAuthorityRevision(workdirInput, selection = {}) {
48
48
  revision: decision,
49
49
  selection,
50
50
  });
51
+ if (proposal.change_class === "mechanically_bounded_repair")
52
+ return result({
53
+ status: "automatic_revision_available",
54
+ activeIdentity: active.active_authority_identity,
55
+ candidateIdentity: candidate.compiled_identity,
56
+ revision: decision,
57
+ selection,
58
+ });
51
59
  if (proposal.change_class !== "scope_only_expansion")
52
60
  return result({
53
61
  status: "protected_change_previewed",
@@ -1,7 +1,7 @@
1
1
  import { changedAuthoritySections } from "./long-task-authority.js";
2
2
  import { authorityMaterialHashes, compiledAuthorityMaterials, } from "./long-task-authority-materials.js";
3
3
  import { authorityRevisionDiff } from "./long-task-authority-revision.js";
4
- import { classifyAuthorityRevision, summarizeAuthorityRevision, } from "./long-task-authority-revision-summary.js";
4
+ import { authorityRevisionUserDecisionReasons, classifyAuthorityRevision, summarizeAuthorityRevision, } from "./long-task-authority-revision-summary.js";
5
5
  import { authorityRevisionApproved, writePendingAuthorityRevision, } from "./long-task-state.js";
6
6
  import { canonicalValueJson, sha256Hex } from "./strict-codec.js";
7
7
  export function assertRiskNotDowngraded(previous, nextLevel, nextReasons) {
@@ -16,6 +16,8 @@ export function buildAuthorityRevisionProposal(previous, nextContract, nextHashe
16
16
  const previousMaterials = compiledAuthorityMaterials(previous);
17
17
  const diff = authorityRevisionDiff(previous, nextContract, nextHashes, nextMaterials, nextGlobalChecks, nextOutcomes, nextVerifier);
18
18
  const changeClass = classifyAuthorityRevision(diff);
19
+ const userDecisionReasons = authorityRevisionUserDecisionReasons(diff);
20
+ const userDecisionRequired = userDecisionReasons.length > 0;
19
21
  const approvalSummary = summarizeAuthorityRevision(diff, nextContract.outcomes.map((outcome) => outcome.key));
20
22
  const unsignedRevision = {
21
23
  previous_hashes: previous.authority_hashes,
@@ -29,14 +31,16 @@ export function buildAuthorityRevisionProposal(previous, nextContract, nextHashe
29
31
  new_risk_floor: riskFloor,
30
32
  affected_outcomes_or_contracts: approvalSummary.affected_outcomes,
31
33
  change_class: changeClass,
32
- approval_required: diff.reduction_reasons.length > 0,
34
+ user_decision_required: userDecisionRequired,
35
+ user_decision_reasons: userDecisionReasons,
36
+ approval_required: userDecisionRequired,
33
37
  approval_summary: approvalSummary,
34
38
  };
35
39
  const revisionIdentity = sha256Hex(canonicalValueJson(unsignedRevision));
36
40
  return { ...unsignedRevision, revision_identity: revisionIdentity };
37
41
  }
38
42
  export async function enforceAuthorityRevision(proposal, workdir) {
39
- if (!proposal.approval_required)
43
+ if (!proposal.user_decision_required)
40
44
  return;
41
45
  if (!(await authorityRevisionApproved(workdir, proposal.revision_identity))) {
42
46
  await writePendingAuthorityRevision(workdir, {
@@ -1,11 +1,14 @@
1
1
  import type { AuthorityRevisionApprovalSummaryV2, AuthorityRevisionChangeClassV2, AuthorityRevisionDecisionV2, AuthorityRevisionDiffV2 } from "./long-task-authority-revision-types.js";
2
2
  export declare function classifyAuthorityRevision(diff: AuthorityRevisionDiffV2): AuthorityRevisionChangeClassV2;
3
+ export declare function authorityRevisionUserDecisionReasons(diff: AuthorityRevisionDiffV2): string[];
3
4
  export declare function summarizeAuthorityRevision(diff: AuthorityRevisionDiffV2, outcomeKeys: string[]): AuthorityRevisionApprovalSummaryV2;
4
5
  export declare function projectAuthorityRevisionDecision(value: {
5
6
  revision_identity: string;
6
7
  revision_diff: AuthorityRevisionDiffV2;
7
8
  affected_outcomes_or_contracts: string[];
8
9
  change_class?: AuthorityRevisionChangeClassV2;
10
+ user_decision_required?: boolean;
11
+ user_decision_reasons?: string[];
9
12
  approval_required?: boolean;
10
13
  approval_summary?: AuthorityRevisionApprovalSummaryV2;
11
14
  }): AuthorityRevisionDecisionV2;
@@ -1,18 +1,59 @@
1
+ import { buildAuthorityRevisionDecisionBrief } from "./long-task-authority-revision-brief.js";
1
2
  const SCOPE_EXPANSION_REASONS = new Set([
2
3
  "owner_path_expanded",
3
4
  "expected_change_path_expanded",
4
5
  "allowed_path_expanded",
5
6
  ]);
7
+ const MECHANICALLY_BOUNDED_REASONS = new Set([
8
+ "source_file_content_changed",
9
+ "context_authority_changed",
10
+ "verification_input_removed_or_replaced",
11
+ "environment_requirement_removed",
12
+ "risk_changed_requires_review",
13
+ ]);
14
+ const USER_DECISION_REASONS = new Set([
15
+ "product_claim_added",
16
+ "product_claim_removed",
17
+ "product_claim_changed",
18
+ "global_semantics_changed",
19
+ "source_claim_removed_or_changed",
20
+ "source_claim_added",
21
+ "source_path_removed_or_replaced",
22
+ "check_removed",
23
+ "negative_assertion_removed",
24
+ "acceptance_semantics_reduced",
25
+ "proof_surface_changed",
26
+ "input_path_coverage_reduced",
27
+ "expected_output_requirement_weakened",
28
+ "artifact_removed",
29
+ "owner_context_ref_removed",
30
+ "forbidden_path_removed",
31
+ "obligation_removed_or_weakened",
32
+ "rollback_or_recovery_weakened",
33
+ "counterfactual_removed",
34
+ "population_weakened",
35
+ "verifier_content_changed",
36
+ "external_confirmation_changed",
37
+ ]);
38
+ const AUTOMATIC_RUNNER_FIELDS = new Set([
39
+ "target",
40
+ "argv",
41
+ "cwd",
42
+ "timeout_ms",
43
+ "retry_policy",
44
+ "idempotent",
45
+ "resolved_target",
46
+ "resolved_cwd",
47
+ "package_script",
48
+ ]);
6
49
  const PROOF_REDUCTION_REASONS = new Set([
7
50
  "check_removed",
8
51
  "negative_assertion_removed",
52
+ "acceptance_semantics_reduced",
9
53
  "proof_surface_changed",
10
- "runner_definition_changed",
11
- "verification_input_removed_or_replaced",
12
54
  "input_path_coverage_reduced",
13
55
  "expected_output_requirement_weakened",
14
56
  "artifact_removed",
15
- "environment_requirement_removed",
16
57
  "binding_removed_or_expanded",
17
58
  "obligation_removed_or_weakened",
18
59
  "rollback_or_recovery_weakened",
@@ -24,13 +65,54 @@ const PROOF_REDUCTION_REASONS = new Set([
24
65
  export function classifyAuthorityRevision(diff) {
25
66
  if (!diff.reduction_reasons.length)
26
67
  return "monotonic_evidence_strengthening";
68
+ const userDecisionReasons = authorityRevisionUserDecisionReasons(diff);
27
69
  if (diff.reduction_reasons.every((reason) => SCOPE_EXPANSION_REASONS.has(reason)))
28
70
  return "scope_only_expansion";
71
+ if (!userDecisionReasons.length)
72
+ return "mechanically_bounded_repair";
29
73
  return "protected_semantic_or_proof_change";
30
74
  }
75
+ export function authorityRevisionUserDecisionReasons(diff) {
76
+ const reasons = [];
77
+ for (const reason of diff.reduction_reasons) {
78
+ if (USER_DECISION_REASONS.has(reason)) {
79
+ reasons.push(reason);
80
+ continue;
81
+ }
82
+ if (SCOPE_EXPANSION_REASONS.has(reason) ||
83
+ MECHANICALLY_BOUNDED_REASONS.has(reason))
84
+ continue;
85
+ if (reason === "product_semantics_changed") {
86
+ if (diff.product_semantics_changed.some(isDecisionProductSemanticField))
87
+ reasons.push(reason);
88
+ continue;
89
+ }
90
+ if (reason === "runner_definition_changed") {
91
+ if (diff.runner_definitions_changed.some((entry) => !AUTOMATIC_RUNNER_FIELDS.has(lastAddressPart(entry))))
92
+ reasons.push(reason);
93
+ continue;
94
+ }
95
+ if (reason === "binding_removed_or_expanded") {
96
+ if (diff.bindings_removed_or_expanded.some((entry) => entry.endsWith(":removed") ||
97
+ entry.endsWith(":target_or_kind_changed")))
98
+ reasons.push(reason);
99
+ continue;
100
+ }
101
+ if (reason === "acceptance_not_monotonic") {
102
+ if (!hasMechanicallyExplainedAcceptanceChange(diff))
103
+ reasons.push(reason);
104
+ continue;
105
+ }
106
+ // New or unknown reason codes fail closed until this policy owner
107
+ // explicitly classifies them.
108
+ reasons.push(reason);
109
+ }
110
+ return uniqueSorted(reasons);
111
+ }
31
112
  export function summarizeAuthorityRevision(diff, outcomeKeys) {
32
113
  const affectedOutcomes = scopeAffectedOutcomes(diff);
33
114
  const changeClass = classifyAuthorityRevision(diff);
115
+ const userDecisionReasons = authorityRevisionUserDecisionReasons(diff);
34
116
  return {
35
117
  product_semantics_changed: diff.product_claims_added.length > 0 ||
36
118
  diff.product_claims_removed.length > 0 ||
@@ -50,7 +132,7 @@ export function summarizeAuthorityRevision(diff, outcomeKeys) {
50
132
  diff.context_files_added.length > 0 ||
51
133
  diff.context_files_removed.length > 0 ||
52
134
  diff.context_files_changed.length > 0,
53
- acceptance_or_proof_weakened: diff.reduction_reasons.some((reason) => PROOF_REDUCTION_REASONS.has(reason)),
135
+ acceptance_or_proof_weakened: userDecisionReasons.some((reason) => PROOF_REDUCTION_REASONS.has(reason)),
54
136
  verifier_or_runner_changed: diff.verifier_content_changed ||
55
137
  diff.verifier_runtime_locator_changed ||
56
138
  diff.runner_definitions_changed.length > 0,
@@ -79,6 +161,8 @@ export function summarizeAuthorityRevision(diff, outcomeKeys) {
79
161
  expanded_owner_paths: uniqueSorted(diff.owner_paths_expanded),
80
162
  expanded_expected_change_paths: uniqueSorted(diff.expected_change_paths_expanded),
81
163
  expanded_allowed_support_paths: uniqueSorted(diff.allowed_paths_expanded),
164
+ user_decision_reasons: userDecisionReasons,
165
+ mechanically_bounded_reasons: uniqueSorted(diff.reduction_reasons.filter((reason) => !userDecisionReasons.includes(reason))),
82
166
  protected_reasons: uniqueSorted(diff.reduction_reasons),
83
167
  affected_outcomes: changeClass === "scope_only_expansion" && affectedOutcomes.length > 0
84
168
  ? affectedOutcomes
@@ -90,32 +174,60 @@ export function projectAuthorityRevisionDecision(value) {
90
174
  ...value.revision_diff,
91
175
  verification_inputs_added: value.revision_diff.verification_inputs_added ?? [],
92
176
  input_paths_added: value.revision_diff.input_paths_added ?? [],
177
+ acceptance_semantics_reduced: value.revision_diff.acceptance_semantics_reduced ?? [],
93
178
  external_confirmations_changed: value.revision_diff.external_confirmations_changed ?? false,
94
179
  external_confirmation_changes: value.revision_diff.external_confirmation_changes ?? [],
95
180
  };
96
181
  const computedSummary = summarizeAuthorityRevision(diff, value.affected_outcomes_or_contracts);
97
182
  const storedSummary = value.approval_summary;
183
+ const approvalSummary = storedSummary
184
+ ? {
185
+ ...computedSummary,
186
+ ...storedSummary,
187
+ semantic_fields_changed: storedSummary.semantic_fields_changed ??
188
+ computedSummary.semantic_fields_changed,
189
+ source_claim_changes: storedSummary.source_claim_changes ??
190
+ computedSummary.source_claim_changes,
191
+ product_claim_changes: storedSummary.product_claim_changes ??
192
+ computedSummary.product_claim_changes,
193
+ proof_reductions: storedSummary.proof_reductions ?? computedSummary.proof_reductions,
194
+ external_confirmation_changes: storedSummary.external_confirmation_changes ??
195
+ computedSummary.external_confirmation_changes,
196
+ user_decision_reasons: storedSummary.user_decision_reasons ??
197
+ computedSummary.user_decision_reasons,
198
+ mechanically_bounded_reasons: storedSummary.mechanically_bounded_reasons ??
199
+ computedSummary.mechanically_bounded_reasons,
200
+ }
201
+ : computedSummary;
202
+ const changeClass = value.change_class ?? classifyAuthorityRevision(diff);
203
+ const computedUserDecisionReasons = authorityRevisionUserDecisionReasons(diff);
204
+ const userDecisionRequired = value.user_decision_required ??
205
+ value.approval_required ??
206
+ computedUserDecisionReasons.length > 0;
207
+ const userDecisionReasons = value.user_decision_reasons ??
208
+ approvalSummary.user_decision_reasons ??
209
+ computedUserDecisionReasons;
98
210
  return {
99
211
  revision_identity: value.revision_identity,
100
- change_class: value.change_class ?? classifyAuthorityRevision(diff),
101
- approval_required: value.approval_required ?? true,
102
- approval_summary: storedSummary
103
- ? {
104
- ...computedSummary,
105
- ...storedSummary,
106
- semantic_fields_changed: storedSummary.semantic_fields_changed ??
107
- computedSummary.semantic_fields_changed,
108
- source_claim_changes: storedSummary.source_claim_changes ??
109
- computedSummary.source_claim_changes,
110
- product_claim_changes: storedSummary.product_claim_changes ??
111
- computedSummary.product_claim_changes,
112
- proof_reductions: storedSummary.proof_reductions ?? computedSummary.proof_reductions,
113
- external_confirmation_changes: storedSummary.external_confirmation_changes ??
114
- computedSummary.external_confirmation_changes,
115
- }
116
- : computedSummary,
212
+ change_class: changeClass,
213
+ user_decision_required: userDecisionRequired,
214
+ user_decision_reasons: userDecisionReasons,
215
+ approval_required: userDecisionRequired,
216
+ approval_summary: approvalSummary,
217
+ decision_brief: buildAuthorityRevisionDecisionBrief(approvalSummary, changeClass, userDecisionRequired),
117
218
  };
118
219
  }
220
+ function isDecisionProductSemanticField(field) {
221
+ return (!/^stages\.[^.]+\.title$/u.test(field) &&
222
+ !/^outcomes\.[^.]+\.title$/u.test(field));
223
+ }
224
+ function lastAddressPart(value) {
225
+ return value.slice(value.lastIndexOf(":") + 1);
226
+ }
227
+ function hasMechanicallyExplainedAcceptanceChange(diff) {
228
+ return (diff.verification_inputs_removed_or_replaced.length > 0 ||
229
+ diff.environment_requirements_removed.length > 0);
230
+ }
119
231
  function scopeAffectedOutcomes(diff) {
120
232
  return uniqueSorted([
121
233
  ...diff.owner_paths_expanded,
@@ -1,5 +1,5 @@
1
1
  import type { AuthorityHashesV2, AuthorityMaterialHashesV2, NextAuthorityMaterialsV2, VerifierIdentityV2 } from "./long-task-authority-types.js";
2
- export type AuthorityRevisionChangeClassV2 = "monotonic_evidence_strengthening" | "scope_only_expansion" | "protected_semantic_or_proof_change";
2
+ export type AuthorityRevisionChangeClassV2 = "monotonic_evidence_strengthening" | "mechanically_bounded_repair" | "scope_only_expansion" | "protected_semantic_or_proof_change";
3
3
  export interface AuthorityRevisionApprovalSummaryV2 {
4
4
  product_semantics_changed: boolean;
5
5
  global_or_technical_semantics_changed: boolean;
@@ -19,6 +19,8 @@ export interface AuthorityRevisionApprovalSummaryV2 {
19
19
  expanded_owner_paths: string[];
20
20
  expanded_expected_change_paths: string[];
21
21
  expanded_allowed_support_paths: string[];
22
+ user_decision_reasons: string[];
23
+ mechanically_bounded_reasons: string[];
22
24
  protected_reasons: string[];
23
25
  affected_outcomes: string[];
24
26
  }
@@ -34,15 +36,30 @@ export interface AuthorityRevisionProposalV2 {
34
36
  new_risk_floor: "standard" | "strict";
35
37
  affected_outcomes_or_contracts: string[];
36
38
  change_class: AuthorityRevisionChangeClassV2;
39
+ user_decision_required: boolean;
40
+ user_decision_reasons: string[];
41
+ /** Compatibility alias for user_decision_required. */
37
42
  approval_required: boolean;
38
43
  approval_summary: AuthorityRevisionApprovalSummaryV2;
39
44
  revision_identity: string;
40
45
  }
46
+ export interface AuthorityRevisionDecisionBriefV2 {
47
+ overview: string;
48
+ headline: string;
49
+ approval_reason: string;
50
+ material_changes: string[];
51
+ affected_outcomes: string[];
52
+ if_approved: string[];
53
+ }
41
54
  export interface AuthorityRevisionDecisionV2 {
42
55
  revision_identity: string;
43
56
  change_class: AuthorityRevisionChangeClassV2;
57
+ user_decision_required: boolean;
58
+ user_decision_reasons: string[];
59
+ /** Compatibility alias for user_decision_required. */
44
60
  approval_required: boolean;
45
61
  approval_summary: AuthorityRevisionApprovalSummaryV2;
62
+ decision_brief: AuthorityRevisionDecisionBriefV2;
46
63
  }
47
64
  export interface AuthorityRevisionDiffV2 {
48
65
  product_claims_added: string[];
@@ -53,6 +70,7 @@ export interface AuthorityRevisionDiffV2 {
53
70
  checks_added: string[];
54
71
  checks_removed: string[];
55
72
  negative_assertions_removed: string[];
73
+ acceptance_semantics_reduced: string[];
56
74
  proof_surfaces_changed: string[];
57
75
  source_claims_added: string[];
58
76
  source_claims_removed_or_changed: string[];
@@ -39,6 +39,10 @@ export function authorityRevisionDiff(previous, next, nextHashes, nextMaterials,
39
39
  ...selectedRevisionReasons([
40
40
  ["check_removed", checksRemoved],
41
41
  ["negative_assertion_removed", checkChanges.negative_assertions_removed],
42
+ [
43
+ "acceptance_semantics_reduced",
44
+ checkChanges.acceptance_semantics_reduced,
45
+ ],
42
46
  ["proof_surface_changed", checkChanges.proof_surfaces_changed],
43
47
  ["source_claim_removed_or_changed", sourceClaimsRemovedOrChanged],
44
48
  ["source_claim_added", sourceClaimsAdded],
@@ -98,6 +102,7 @@ export function authorityRevisionDiff(previous, next, nextHashes, nextMaterials,
98
102
  checks_added: addedValues(new Set(beforeChecks.keys()), new Set(afterChecks.keys())),
99
103
  checks_removed: checksRemoved,
100
104
  negative_assertions_removed: checkChanges.negative_assertions_removed,
105
+ acceptance_semantics_reduced: checkChanges.acceptance_semantics_reduced,
101
106
  proof_surfaces_changed: checkChanges.proof_surfaces_changed,
102
107
  source_claims_added: sourceClaimsAdded,
103
108
  source_claims_removed_or_changed: sourceClaimsRemovedOrChanged,
@@ -1,5 +1,6 @@
1
1
  import type { ProofSurface } from "./long-task-contract-types.js";
2
2
  import type { DeliveryStageV2, ExecutionTargetV2, TargetProfileV2 } from "./long-task-semantic-contract-types.js";
3
+ import type { DeliverySurfaceBindingV2 } from "./long-task-ui-surface-types.js";
3
4
  import type { CompiledSourceItemV2 } from "./long-task-source-authority-types.js";
4
5
  import type { WorkspaceManifestV2 } from "./long-task-workspace-runtime-types.js";
5
6
  export interface AuthorityHashesV2 {
@@ -59,6 +60,7 @@ export interface ProductSemanticProjectionV2 {
59
60
  feedback: string;
60
61
  accessibility: string;
61
62
  }>;
63
+ surface_bindings: DeliverySurfaceBindingV2[];
62
64
  non_completing_outcomes: Array<{
63
65
  key: string;
64
66
  statement: string;
@@ -79,7 +79,7 @@ export function isMonotonicAcceptanceStrengthening(previous, next) {
79
79
  if (!acceptanceSemanticsChanged(previous, next))
80
80
  return false;
81
81
  if (!same(previous.global.acceptance.external_confirmations, next.global.acceptance.external_confirmations) ||
82
- !subset(previous.global.acceptance.counterfactual_controls ?? [], next.global.acceptance.counterfactual_controls) ||
82
+ !counterfactualsStrengthened(previous.global.acceptance.counterfactual_controls ?? [], next.global.acceptance.counterfactual_controls) ||
83
83
  !checksStrengthened(previous.global.acceptance.checks, next.global.acceptance.checks))
84
84
  return false;
85
85
  const nextOutcomes = new Map(next.outcomes.map((outcome) => [outcome.key, outcome]));
@@ -91,7 +91,7 @@ export function isMonotonicAcceptanceStrengthening(previous, next) {
91
91
  return false;
92
92
  if (!checksStrengthened(previousOutcome.acceptance.checks, nextOutcome.acceptance.checks) ||
93
93
  !optionalStrengthened(previousOutcome.acceptance.population, nextOutcome.acceptance.population) ||
94
- !subset(previousOutcome.acceptance.counterfactual_controls, nextOutcome.acceptance.counterfactual_controls))
94
+ !counterfactualsStrengthened(previousOutcome.acceptance.counterfactual_controls, nextOutcome.acceptance.counterfactual_controls))
95
95
  return false;
96
96
  }
97
97
  return true;
@@ -154,6 +154,14 @@ function assertionsStrengthened(previous, next) {
154
154
  }
155
155
  return true;
156
156
  }
157
+ function counterfactualsStrengthened(previous, next) {
158
+ return previous.every((control) => next.some((candidate) => same(candidate.binding_key, control.binding_key) &&
159
+ same(candidate.binding_ref, control.binding_ref) &&
160
+ candidate.check_key === control.check_key &&
161
+ same(candidate.mutation, control.mutation) &&
162
+ subset(control.claims, candidate.claims) &&
163
+ subset(control.expected_assertion_failures, candidate.expected_assertion_failures)));
164
+ }
157
165
  function subset(previous, next) {
158
166
  const available = new Set(next.map((item) => canonicalValueJson(item)));
159
167
  return previous.every((item) => available.has(canonicalValueJson(item)));
@@ -19,6 +19,8 @@ export function rawExecutionInputProjection(check) {
19
19
  projection.evidence_adapter = check.evidence_adapter;
20
20
  projection.execution_target_definition = check.execution_target_definition;
21
21
  projection.known_execution_targets = check.known_execution_targets;
22
+ projection.design_conformance_targets =
23
+ check.design_conformance_targets ?? [];
22
24
  for (const field of Object.keys(CHECK_EXECUTION_INPUT_POLICY)) {
23
25
  const policy = CHECK_EXECUTION_INPUT_POLICY[field];
24
26
  if (policy === "raw_execution") {
@@ -30,9 +30,7 @@ export function generateClaims(outcome) {
30
30
  ];
31
31
  for (const [field, value] of fields)
32
32
  if (value.trim())
33
- claims.push(claim(outcome.key, `control.${control.key}.${field}`, "control", [
34
- "ui_browser",
35
- ]));
33
+ claims.push(claim(outcome.key, `control.${control.key}.${field}`, "control"));
36
34
  }
37
35
  for (const item of outcome.product.non_completing_outcomes)
38
36
  claims.push(claim(outcome.key, `non_completing.${item.key}`, "non_completing"));
@@ -54,8 +52,6 @@ export function validateGlobalProofPolarity(claim, proof) {
54
52
  fail("global_negative_claim_proof_required", `${claim.local_key}:${proof.check_key}`);
55
53
  }
56
54
  export function validateProofSurface(claim, proof, outcomeKey) {
57
- if (claim.kind === "control" && proof.proof_surface !== "ui_browser")
58
- fail("ui_claim_requires_ui_browser", `${outcomeKey}:${claim.local_key}`);
59
55
  if ((claim.kind === "non_completing" || claim.kind === "forbidden_shortcut") &&
60
56
  proof.polarity !== "negative" &&
61
57
  proof.polarity !== "counterfactual")
@@ -1,6 +1,7 @@
1
1
  import type { LongTaskRiskFacts, RequestedRiskLevel } from "./long-task-risk-types.js";
2
2
  import type { CounterfactualControlV2, GlobalCounterfactualControlV2 } from "./long-task-counterfactual-types.js";
3
3
  import type { CheckExecutionTargetV2, DeliveryJourneyRoleV2, DeliveryScenarioV2, DeliveryStageV2, EvidenceCapabilityV2, ExecutionTargetV2, ExternalConfirmationKindV2, KeyedStatementV2, TargetProfileV2 } from "./long-task-semantic-contract-types.js";
4
+ import type { DeliverySurfaceBindingV2 } from "./long-task-ui-surface-types.js";
4
5
  export type SourceClaimDispositionV2 = {
5
6
  type: "claim";
6
7
  refs: string[];
@@ -172,6 +173,7 @@ export interface DeliveryOutcomeV2 {
172
173
  requirements: DeliveryRequirementV2[];
173
174
  owner_surfaces: string[];
174
175
  controls: DeliveryControlV2[];
176
+ surface_bindings: DeliverySurfaceBindingV2[];
175
177
  non_completing_outcomes: KeyedStatementV2[];
176
178
  };
177
179
  technical: {
@@ -3,4 +3,11 @@ export interface CounterfactualSandboxV2 {
3
3
  root: string;
4
4
  dispose(): Promise<void>;
5
5
  }
6
+ type RemoveTree = (target: string, options: {
7
+ recursive: true;
8
+ force: true;
9
+ }) => Promise<void>;
10
+ type Wait = (milliseconds: number) => Promise<void>;
6
11
  export declare function createCounterfactualSandbox(snapshotRoot: string, check: CompiledCheckV2, control: CounterfactualControlV2 | GlobalCounterfactualControlV2, bindingCarrierPaths: string[], manifest?: WorkspaceManifestV2): Promise<CounterfactualSandboxV2>;
12
+ export declare function removeCounterfactualSandboxRoot(root: string, removeTree?: RemoveTree, wait?: Wait): Promise<void>;
13
+ export {};
@@ -2,6 +2,15 @@ import { copyFile, cp, lstat, mkdir, mkdtemp, readlink, realpath, rm, symlink, }
2
2
  import os from "node:os";
3
3
  import path from "node:path";
4
4
  import { matchesRepoPattern } from "./long-task-paths.js";
5
+ const TRANSIENT_REMOVE_CODES = new Set([
6
+ "EBUSY",
7
+ "EMFILE",
8
+ "ENFILE",
9
+ "ENOTEMPTY",
10
+ "EPERM",
11
+ ]);
12
+ const REMOVE_RETRY_LIMIT = process.platform === "win32" ? 6 : 2;
13
+ const REMOVE_RETRY_DELAY_MS = 100;
5
14
  export async function createCounterfactualSandbox(snapshotRoot, check, control, bindingCarrierPaths, manifest) {
6
15
  const root = await mkdtemp(path.join(os.tmpdir(), "ty-context-counterfactual-"));
7
16
  if (!manifest) {
@@ -81,7 +90,24 @@ function disposable(root) {
81
90
  return {
82
91
  root,
83
92
  async dispose() {
84
- await rm(root, { recursive: true, force: true });
93
+ await removeCounterfactualSandboxRoot(root);
85
94
  },
86
95
  };
87
96
  }
97
+ export async function removeCounterfactualSandboxRoot(root, removeTree = rm, wait = (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds))) {
98
+ for (let attempt = 0;; attempt += 1) {
99
+ try {
100
+ await removeTree(root, { recursive: true, force: true });
101
+ return;
102
+ }
103
+ catch (error) {
104
+ const code = error && typeof error === "object" && "code" in error
105
+ ? String(error.code)
106
+ : "";
107
+ if (!TRANSIENT_REMOVE_CODES.has(code) ||
108
+ attempt >= REMOVE_RETRY_LIMIT)
109
+ throw error;
110
+ await wait(REMOVE_RETRY_DELAY_MS * (attempt + 1));
111
+ }
112
+ }
113
+ }