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.
- package/LICENSE +21 -21
- package/README.md +393 -380
- package/assets/README.md +567 -557
- package/assets/README.zh-CN.md +339 -326
- package/assets/agents/.gitkeep +1 -1
- package/assets/agents/AGENTS_CORE.md +66 -64
- package/assets/context_templates/architecture.md +33 -33
- package/assets/context_templates/area.md +39 -39
- package/assets/context_templates/context.toml +30 -30
- package/assets/context_templates/deployment.md +35 -35
- package/assets/context_templates/global.md +52 -51
- package/assets/context_templates/product-surface-contract.md +70 -70
- package/assets/context_templates/screen-contract.md +186 -177
- package/assets/context_templates/verification.md +32 -32
- package/assets/github/.gitkeep +1 -1
- package/assets/github/harness.yml +41 -41
- package/assets/make/.gitkeep +1 -1
- package/assets/make/ty-context.mk +48 -48
- package/assets/skills/context_development_engineer/SKILL.md +135 -131
- package/assets/skills/context_full_project_export/SKILL.md +70 -70
- package/assets/skills/context_harness_upgrade/SKILL.md +60 -60
- package/assets/skills/context_product_plan/SKILL.md +88 -87
- package/assets/skills/context_surface_contract/SKILL.md +191 -191
- package/assets/skills/context_uiux_design/SKILL.md +158 -154
- package/assets/skills/design-resource-authoring/SKILL.md +84 -79
- package/assets/skills/design-resource-authoring/references/downstream-handoff.md +136 -108
- package/assets/skills/design-resource-authoring/references/open-design-provider.md +133 -127
- 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 -47
- package/assets/skills/design-system-authoring/references/open-design-design-system-provider.md +110 -110
- package/assets/skills/long-task-workflow/SKILL.md +100 -92
- package/assets/skills/long-task-workflow/agents/openai.yaml +4 -4
- package/assets/skills/long-task-workflow/references/authority-lifecycle.md +76 -59
- package/assets/skills/long-task-workflow/references/contract-authoring.md +116 -105
- package/assets/skills/long-task-workflow/references/evidence-design.md +78 -75
- package/assets/skills/long-task-workflow/references/source-authoring.md +101 -98
- package/assets/skills/normal-long-task/SKILL.md +12 -12
- package/assets/skills/source-plan-authoring/SKILL.md +14 -14
- package/assets/tools/validate_context.py +442 -442
- package/dist/commands/design-resource.d.ts +1 -0
- package/dist/commands/design-resource.js +32 -0
- package/dist/commands/index.js +4 -0
- package/dist/commands/long-task-command-args.d.ts +1 -0
- package/dist/commands/long-task-command-args.js +6 -0
- package/dist/commands/long-task-revision.js +16 -4
- package/dist/commands/long-task.js +12 -5
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/lib/design-md.js +3 -1
- package/dist/lib/design-resource-handoff-file-primitives.d.ts +4 -0
- package/dist/lib/design-resource-handoff-file-primitives.js +14 -0
- package/dist/lib/design-resource-handoff-file-validation.d.ts +2 -0
- package/dist/lib/design-resource-handoff-file-validation.js +142 -0
- package/dist/lib/design-resource-handoff-parser.d.ts +3 -0
- package/dist/lib/design-resource-handoff-parser.js +29 -0
- package/dist/lib/design-resource-handoff-policy.d.ts +3 -0
- package/dist/lib/design-resource-handoff-policy.js +36 -0
- package/dist/lib/design-resource-handoff-shape-evidence.d.ts +4 -0
- package/dist/lib/design-resource-handoff-shape-evidence.js +84 -0
- package/dist/lib/design-resource-handoff-shape-primitives.d.ts +9 -0
- package/dist/lib/design-resource-handoff-shape-primitives.js +44 -0
- package/dist/lib/design-resource-handoff-shape-structure.d.ts +5 -0
- package/dist/lib/design-resource-handoff-shape-structure.js +118 -0
- package/dist/lib/design-resource-handoff-shape.d.ts +2 -0
- package/dist/lib/design-resource-handoff-shape.js +75 -0
- package/dist/lib/design-resource-handoff-types.d.ts +139 -0
- package/dist/lib/design-resource-handoff-types.js +46 -0
- package/dist/lib/design-resource-handoff-validation-coverage.d.ts +4 -0
- package/dist/lib/design-resource-handoff-validation-coverage.js +168 -0
- package/dist/lib/design-resource-handoff-validation-primitives.d.ts +11 -0
- package/dist/lib/design-resource-handoff-validation-primitives.js +26 -0
- package/dist/lib/design-resource-handoff-validation-structure.d.ts +6 -0
- package/dist/lib/design-resource-handoff-validation-structure.js +93 -0
- package/dist/lib/design-resource-handoff-validation.d.ts +3 -0
- package/dist/lib/design-resource-handoff-validation.js +78 -0
- package/dist/lib/design-resource-handoff-web-dependency-validation.d.ts +3 -0
- package/dist/lib/design-resource-handoff-web-dependency-validation.js +70 -0
- package/dist/lib/long-task-activation-validation.js +14 -2
- package/dist/lib/long-task-authoring-preflight-diagnostics.js +7 -0
- package/dist/lib/long-task-authoring-preflight.js +39 -1
- package/dist/lib/long-task-authority-material-diff.js +14 -0
- package/dist/lib/long-task-authority-materials.js +21 -0
- package/dist/lib/long-task-authority-policy.d.ts +33 -0
- package/dist/lib/long-task-authority-policy.js +36 -0
- package/dist/lib/long-task-authority-revision-analysis.d.ts +1 -0
- package/dist/lib/long-task-authority-revision-analysis.js +30 -0
- package/dist/lib/long-task-authority-revision-brief.d.ts +3 -0
- package/dist/lib/long-task-authority-revision-brief.js +74 -0
- package/dist/lib/long-task-authority-revision-details.js +16 -16
- package/dist/lib/long-task-authority-revision-diagnosis.d.ts +1 -1
- package/dist/lib/long-task-authority-revision-diagnosis.js +8 -0
- package/dist/lib/long-task-authority-revision-enforcement.js +7 -3
- package/dist/lib/long-task-authority-revision-summary.d.ts +3 -0
- package/dist/lib/long-task-authority-revision-summary.js +133 -21
- package/dist/lib/long-task-authority-revision-types.d.ts +19 -1
- package/dist/lib/long-task-authority-revision.js +5 -0
- package/dist/lib/long-task-authority-types.d.ts +2 -0
- package/dist/lib/long-task-authority.js +10 -2
- package/dist/lib/long-task-check-execution-policy.js +2 -0
- package/dist/lib/long-task-claim-definitions.js +1 -5
- package/dist/lib/long-task-contract-types.d.ts +2 -0
- package/dist/lib/long-task-counterfactual-sandbox.d.ts +7 -0
- package/dist/lib/long-task-counterfactual-sandbox.js +27 -1
- package/dist/lib/long-task-delivery-compiler.js +26 -8
- 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 +3 -0
- package/dist/lib/long-task-design-resource-handoff.d.ts +2 -0
- package/dist/lib/long-task-design-resource-handoff.js +177 -0
- package/dist/lib/long-task-evidence-capability-codec.js +19 -0
- package/dist/lib/long-task-evidence-capability-policy.js +4 -0
- package/dist/lib/long-task-evidence-capability-runtime.js +25 -0
- package/dist/lib/long-task-evidence-capability-types.d.ts +9 -1
- package/dist/lib/long-task-outcome-parser.js +11 -1
- package/dist/lib/long-task-paths.d.ts +0 -1
- package/dist/lib/long-task-paths.js +0 -4
- package/dist/lib/long-task-playwright-case-evidence.d.ts +43 -0
- package/dist/lib/long-task-playwright-case-evidence.js +152 -0
- package/dist/lib/long-task-playwright-evidence.js +19 -152
- package/dist/lib/long-task-runner-freeze.d.ts +2 -2
- package/dist/lib/long-task-runner-freeze.js +2 -1
- package/dist/lib/long-task-runtime-types.d.ts +2 -0
- package/dist/lib/long-task-semantic-contract-types.d.ts +1 -1
- package/dist/lib/long-task-semantic-drift-migration.js +6 -1
- 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-status-v2.js +12 -7
- package/dist/lib/long-task-ui-design-policy.d.ts +17 -0
- package/dist/lib/long-task-ui-design-policy.js +128 -0
- package/dist/lib/long-task-ui-surface-policy.d.ts +4 -0
- package/dist/lib/long-task-ui-surface-policy.js +109 -0
- package/dist/lib/long-task-ui-surface-shape.d.ts +2 -0
- package/dist/lib/long-task-ui-surface-shape.js +94 -0
- package/dist/lib/long-task-ui-surface-types.d.ts +44 -0
- package/dist/lib/long-task-ui-surface-types.js +1 -0
- package/dist/lib/long-task-ui-surface-validation.d.ts +11 -0
- package/dist/lib/long-task-ui-surface-validation.js +62 -0
- package/dist/lib/long-task-verification-preview.d.ts +55 -0
- package/dist/lib/long-task-verification-preview.js +120 -0
- package/dist/lib/long-task-verifier-v2.js +11 -18
- package/dist/lib/long-task-workspace-scope.d.ts +38 -0
- package/dist/lib/long-task-workspace-scope.js +121 -0
- package/dist/lib/long-task-workspace.d.ts +1 -0
- package/dist/lib/long-task-workspace.js +73 -9
- package/dist/schemas/long-task-delivery-v2/long-task-delivery-v2.schema.json +84 -2
- package/migrations/README.md +7 -7
- package/package.json +3 -3
- 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 =
|
|
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 =
|
|
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
|
-
|
|
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.
|
|
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:
|
|
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:
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
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
|
-
!
|
|
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
|
-
!
|
|
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
|
|
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
|
+
}
|