project-tiny-context-harness 0.7.2 → 0.7.4
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/README.md +7 -5
- package/assets/README.md +49 -14
- package/assets/README.zh-CN.md +26 -13
- package/assets/agents/AGENTS_CORE.md +5 -5
- package/assets/context_templates/global.md +1 -0
- package/assets/skills/context_development_engineer/SKILL.md +4 -1
- package/assets/skills/context_uiux_design/SKILL.md +19 -6
- package/assets/skills/long-task-workflow/SKILL.md +10 -9
- package/assets/skills/long-task-workflow/references/authority-lifecycle.md +7 -5
- package/assets/skills/long-task-workflow/references/contract-authoring.md +24 -6
- package/assets/skills/long-task-workflow/references/evidence-design.md +14 -1
- package/assets/skills/source-plan-authoring/SKILL.md +2 -2
- package/dist/commands/long-task-authoring.js +25 -0
- package/dist/commands/long-task.js +3 -0
- package/dist/lib/design-md.d.ts +3 -0
- package/dist/lib/design-md.js +48 -55
- package/dist/lib/doctor.js +8 -0
- package/dist/lib/long-task-activation-validation.js +13 -2
- package/dist/lib/long-task-authoring-authority-preview.js +1 -0
- package/dist/lib/long-task-authority-material-diff.js +26 -0
- package/dist/lib/long-task-authority-materials.d.ts +2 -2
- package/dist/lib/long-task-authority-materials.js +6 -0
- package/dist/lib/long-task-authority-policy.d.ts +12 -0
- package/dist/lib/long-task-authority-policy.js +9 -0
- package/dist/lib/long-task-authority-revision-analysis.d.ts +33 -0
- package/dist/lib/long-task-authority-revision-analysis.js +91 -0
- package/dist/lib/long-task-authority-revision.js +93 -158
- package/dist/lib/long-task-authority-types.d.ts +7 -0
- package/dist/lib/long-task-authority.js +32 -3
- package/dist/lib/long-task-check-evidence-decoder.d.ts +2 -2
- package/dist/lib/long-task-check-evidence-decoder.js +11 -1
- package/dist/lib/long-task-check-execution-policy.d.ts +3 -0
- package/dist/lib/long-task-check-execution-policy.js +5 -0
- package/dist/lib/long-task-check-runner.js +2 -0
- package/dist/lib/long-task-check-shape.js +33 -3
- package/dist/lib/long-task-conformance-policy.d.ts +5 -0
- package/dist/lib/long-task-conformance-policy.js +35 -0
- package/dist/lib/long-task-contract-types.d.ts +14 -4
- package/dist/lib/long-task-delivery-compiler.js +1 -0
- package/dist/lib/long-task-delivery-parser.js +5 -2
- package/dist/lib/long-task-delivery-types.d.ts +2 -0
- package/dist/lib/long-task-delivery-types.js +2 -0
- package/dist/lib/long-task-delivery-validation.js +11 -0
- package/dist/lib/long-task-evidence-capability-codec.d.ts +2 -0
- package/dist/lib/long-task-evidence-capability-codec.js +231 -0
- package/dist/lib/long-task-evidence-capability-policy.d.ts +8 -0
- package/dist/lib/long-task-evidence-capability-policy.js +147 -0
- package/dist/lib/long-task-evidence-capability-runtime.d.ts +2 -0
- package/dist/lib/long-task-evidence-capability-runtime.js +86 -0
- package/dist/lib/long-task-evidence-capability-types.d.ts +74 -0
- package/dist/lib/long-task-evidence-capability-types.js +1 -0
- package/dist/lib/long-task-evidence-findings.js +5 -1
- package/dist/lib/long-task-evidence-v2.js +38 -23
- package/dist/lib/long-task-final-v2.js +42 -1
- package/dist/lib/long-task-outcome-parser.js +14 -3
- package/dist/lib/long-task-playwright-evidence.d.ts +2 -1
- package/dist/lib/long-task-playwright-evidence.js +70 -2
- package/dist/lib/long-task-progress.js +4 -0
- package/dist/lib/long-task-root-shape.d.ts +1 -0
- package/dist/lib/long-task-root-shape.js +84 -3
- package/dist/lib/long-task-runner-environment.js +1 -1
- package/dist/lib/long-task-runner-freeze.d.ts +2 -2
- package/dist/lib/long-task-runner-freeze.js +3 -1
- package/dist/lib/long-task-runtime-types.d.ts +13 -0
- package/dist/lib/long-task-semantic-contract-types.d.ts +36 -0
- package/dist/lib/long-task-semantic-contract-types.js +1 -0
- package/dist/lib/long-task-semantic-drift-migration.d.ts +3 -0
- package/dist/lib/long-task-semantic-drift-migration.js +68 -0
- package/dist/lib/long-task-shape-primitives.d.ts +3 -0
- package/dist/lib/long-task-shape-primitives.js +25 -0
- package/dist/lib/long-task-stage-policy.d.ts +4 -0
- package/dist/lib/long-task-stage-policy.js +120 -0
- package/dist/lib/long-task-status-projection.d.ts +4 -1
- package/dist/lib/long-task-status-projection.js +63 -3
- package/dist/lib/long-task-status-v2.d.ts +11 -1
- package/dist/lib/long-task-status-v2.js +25 -3
- package/dist/lib/long-task-target-policy.d.ts +6 -0
- package/dist/lib/long-task-target-policy.js +127 -0
- package/dist/lib/migrations.js +29 -0
- package/dist/schemas/long-task-delivery-v2/long-task-delivery-v2.schema.json +61 -7
- package/migrations/README.md +7 -0
- package/package.json +2 -2
|
@@ -20,9 +20,13 @@ export function computeAuthorityHashes(contract) {
|
|
|
20
20
|
}),
|
|
21
21
|
product_authority_hash: hash({
|
|
22
22
|
goal: contract.task.goal,
|
|
23
|
+
target_profile: contract.task.target_profile,
|
|
24
|
+
execution_targets: contract.task.execution_targets,
|
|
25
|
+
stages: contract.stages,
|
|
23
26
|
global: contract.global.product,
|
|
24
27
|
outcomes: contract.outcomes.map((outcome) => ({
|
|
25
28
|
key: outcome.key,
|
|
29
|
+
stage: outcome.stage,
|
|
26
30
|
product: outcome.product,
|
|
27
31
|
})),
|
|
28
32
|
}),
|
|
@@ -51,6 +55,7 @@ export function computeAuthorityHashes(contract) {
|
|
|
51
55
|
}
|
|
52
56
|
export function outcomeAuthorityHash(outcome) {
|
|
53
57
|
return hash({
|
|
58
|
+
stage: outcome.stage,
|
|
54
59
|
product: outcome.product,
|
|
55
60
|
acceptance: {
|
|
56
61
|
checks: outcome.acceptance.checks.map(acceptanceCheck),
|
|
@@ -73,7 +78,7 @@ export function acceptanceSemanticsChanged(previous, next) {
|
|
|
73
78
|
export function isMonotonicAcceptanceStrengthening(previous, next) {
|
|
74
79
|
if (!acceptanceSemanticsChanged(previous, next))
|
|
75
80
|
return false;
|
|
76
|
-
if (!
|
|
81
|
+
if (!same(previous.global.acceptance.external_confirmations, next.global.acceptance.external_confirmations) ||
|
|
77
82
|
!subset(previous.global.acceptance.counterfactual_controls ?? [], next.global.acceptance.counterfactual_controls) ||
|
|
78
83
|
!checksStrengthened(previous.global.acceptance.checks, next.global.acceptance.checks))
|
|
79
84
|
return false;
|
|
@@ -119,8 +124,32 @@ function checksStrengthened(previous, next) {
|
|
|
119
124
|
const nextCheck = nextChecks.get(previousCheck.key);
|
|
120
125
|
if (!nextCheck ||
|
|
121
126
|
previousCheck.proof_surface !== nextCheck.proof_surface ||
|
|
122
|
-
!
|
|
123
|
-
!subset(previousCheck.
|
|
127
|
+
!same(previousCheck.execution_target, nextCheck.execution_target) ||
|
|
128
|
+
!subset(previousCheck.journey_roles, nextCheck.journey_roles) ||
|
|
129
|
+
!subset(previousCheck.scenario.given, nextCheck.scenario.given) ||
|
|
130
|
+
!subset(previousCheck.scenario.when, nextCheck.scenario.when) ||
|
|
131
|
+
!subset(previousCheck.verification_inputs, nextCheck.verification_inputs) ||
|
|
132
|
+
!subset(previousCheck.input_paths, nextCheck.input_paths) ||
|
|
133
|
+
!subset(previousCheck.expected_output_paths, nextCheck.expected_output_paths) ||
|
|
134
|
+
!subset(previousCheck.artifact_globs, nextCheck.artifact_globs) ||
|
|
135
|
+
!subset(previousCheck.environment_requirements, nextCheck.environment_requirements) ||
|
|
136
|
+
!assertionsStrengthened(previousCheck.positive_assertions, nextCheck.positive_assertions) ||
|
|
137
|
+
!assertionsStrengthened(previousCheck.negative_assertions, nextCheck.negative_assertions))
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
function assertionsStrengthened(previous, next) {
|
|
143
|
+
const nextAssertions = new Map(next.map((assertion) => [assertion.key, assertion]));
|
|
144
|
+
for (const previousAssertion of previous) {
|
|
145
|
+
const nextAssertion = nextAssertions.get(previousAssertion.key);
|
|
146
|
+
if (!nextAssertion ||
|
|
147
|
+
previousAssertion.criterion !== nextAssertion.criterion ||
|
|
148
|
+
!same(previousAssertion.claims, nextAssertion.claims) ||
|
|
149
|
+
previousAssertion.observation !== nextAssertion.observation ||
|
|
150
|
+
previousAssertion.operator !== nextAssertion.operator ||
|
|
151
|
+
!same(previousAssertion.expected, nextAssertion.expected) ||
|
|
152
|
+
!subset(previousAssertion.evidence_capabilities, nextAssertion.evidence_capabilities))
|
|
124
153
|
return false;
|
|
125
154
|
}
|
|
126
155
|
return true;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { CompiledCheckV2, RawCommandExecutionV2 } from "./long-task-delivery-types.js";
|
|
2
|
-
export declare function decodeCheckEvidence(check: CompiledCheckV2, exitCode: number, stdout: Buffer, stderr: Buffer): Pick<RawCommandExecutionV2, "execution_status" | "exit_code" | "observations" | "error">;
|
|
3
|
-
export declare function invalidEvidence(exitCode: number, error: string): Pick<RawCommandExecutionV2, "execution_status" | "exit_code" | "observations" | "error">;
|
|
2
|
+
export declare function decodeCheckEvidence(check: CompiledCheckV2, exitCode: number, stdout: Buffer, stderr: Buffer): Pick<RawCommandExecutionV2, "execution_status" | "exit_code" | "observations" | "evidence_records" | "error">;
|
|
3
|
+
export declare function invalidEvidence(exitCode: number, error: string): Pick<RawCommandExecutionV2, "execution_status" | "exit_code" | "observations" | "evidence_records" | "error">;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { extractPlaywrightEvidence } from "./long-task-playwright-evidence.js";
|
|
2
|
+
import { decodeEvidenceCapabilityRecords } from "./long-task-evidence-capability-policy.js";
|
|
2
3
|
export function decodeCheckEvidence(check, exitCode, stdout, stderr) {
|
|
3
4
|
if (check.runner.type === "playwright_test")
|
|
4
5
|
return decodePlaywright(check, exitCode, stdout, stderr);
|
|
@@ -9,13 +10,15 @@ export function decodeCheckEvidence(check, exitCode, stdout, stderr) {
|
|
|
9
10
|
.filter(Boolean);
|
|
10
11
|
try {
|
|
11
12
|
const payload = JSON.parse(lines.at(-1) ?? "");
|
|
12
|
-
if (payload.schema_version !== "long-task-check-result-v2"
|
|
13
|
+
if (payload.schema_version !== "long-task-check-result-v2" &&
|
|
14
|
+
payload.schema_version !== "long-task-check-result-v3")
|
|
13
15
|
return invalidEvidence(exitCode, "check_evidence_schema_invalid");
|
|
14
16
|
if (payload.execution_status === "blocked_external")
|
|
15
17
|
return {
|
|
16
18
|
execution_status: "blocked_external",
|
|
17
19
|
exit_code: exitCode,
|
|
18
20
|
observations: {},
|
|
21
|
+
evidence_records: [],
|
|
19
22
|
error: `blocked_external:${String(payload.reason ?? "unspecified")}`,
|
|
20
23
|
};
|
|
21
24
|
if (payload.execution_status !== "completed")
|
|
@@ -24,10 +27,14 @@ export function decodeCheckEvidence(check, exitCode, stdout, stderr) {
|
|
|
24
27
|
typeof payload.observations !== "object" ||
|
|
25
28
|
Array.isArray(payload.observations))
|
|
26
29
|
return invalidEvidence(exitCode, "check_evidence_observations_invalid");
|
|
30
|
+
const evidenceRecords = payload.schema_version === "long-task-check-result-v3"
|
|
31
|
+
? decodeEvidenceCapabilityRecords(payload.evidence_records)
|
|
32
|
+
: [];
|
|
27
33
|
return {
|
|
28
34
|
execution_status: "completed",
|
|
29
35
|
exit_code: exitCode,
|
|
30
36
|
observations: payload.observations,
|
|
37
|
+
evidence_records: evidenceRecords,
|
|
31
38
|
error: null,
|
|
32
39
|
};
|
|
33
40
|
}
|
|
@@ -40,6 +47,7 @@ export function invalidEvidence(exitCode, error) {
|
|
|
40
47
|
execution_status: "invalid_evidence",
|
|
41
48
|
exit_code: exitCode,
|
|
42
49
|
observations: {},
|
|
50
|
+
evidence_records: [],
|
|
43
51
|
error,
|
|
44
52
|
};
|
|
45
53
|
}
|
|
@@ -53,6 +61,7 @@ function decodePlaywright(check, exitCode, stdout, stderr) {
|
|
|
53
61
|
execution_status: "completed",
|
|
54
62
|
exit_code: exitCode,
|
|
55
63
|
observations: extracted.observations,
|
|
64
|
+
evidence_records: extracted.evidence_records,
|
|
56
65
|
error: null,
|
|
57
66
|
};
|
|
58
67
|
}
|
|
@@ -64,6 +73,7 @@ function decodePlaywright(check, exitCode, stdout, stderr) {
|
|
|
64
73
|
execution_status: "infrastructure_error",
|
|
65
74
|
exit_code: exitCode,
|
|
66
75
|
observations: {},
|
|
76
|
+
evidence_records: [],
|
|
67
77
|
error: `playwright_startup_failed:${message(error)}`,
|
|
68
78
|
};
|
|
69
79
|
return invalidEvidence(exitCode, `playwright_report_invalid:${message(error)}`);
|
|
@@ -2,6 +2,9 @@ import type { CompiledCheckV2 } from "./long-task-delivery-types.js";
|
|
|
2
2
|
export type CheckExecutionInputPolicy = "raw_execution" | "raw_execution_via_runner_freeze" | "per_check_evidence" | "progress_scope" | "final_gate_evidence" | "authority_metadata";
|
|
3
3
|
export declare const CHECK_EXECUTION_INPUT_POLICY: {
|
|
4
4
|
key: "authority_metadata";
|
|
5
|
+
journey_roles: "authority_metadata";
|
|
6
|
+
execution_target: "raw_execution";
|
|
7
|
+
scenario: "per_check_evidence";
|
|
5
8
|
proof_surface: "authority_metadata";
|
|
6
9
|
runner: "raw_execution";
|
|
7
10
|
verification_inputs: "raw_execution_via_runner_freeze";
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { canonicalValueJson, sha256Hex } from "./strict-codec.js";
|
|
2
2
|
export const CHECK_EXECUTION_INPUT_POLICY = {
|
|
3
3
|
key: "authority_metadata",
|
|
4
|
+
journey_roles: "authority_metadata",
|
|
5
|
+
execution_target: "raw_execution",
|
|
6
|
+
scenario: "per_check_evidence",
|
|
4
7
|
proof_surface: "authority_metadata",
|
|
5
8
|
runner: "raw_execution",
|
|
6
9
|
verification_inputs: "raw_execution_via_runner_freeze",
|
|
@@ -14,6 +17,8 @@ export const CHECK_EXECUTION_INPUT_POLICY = {
|
|
|
14
17
|
export function rawExecutionInputProjection(check) {
|
|
15
18
|
const projection = {};
|
|
16
19
|
projection.evidence_adapter = check.evidence_adapter;
|
|
20
|
+
projection.execution_target_definition = check.execution_target_definition;
|
|
21
|
+
projection.known_execution_targets = check.known_execution_targets;
|
|
17
22
|
for (const field of Object.keys(CHECK_EXECUTION_INPUT_POLICY)) {
|
|
18
23
|
const policy = CHECK_EXECUTION_INPUT_POLICY[field];
|
|
19
24
|
if (policy === "raw_execution") {
|
|
@@ -17,6 +17,7 @@ export async function executeCheckRunner(check, snapshotRoot) {
|
|
|
17
17
|
execution_status: "blocked_external",
|
|
18
18
|
exit_code: -1,
|
|
19
19
|
observations: {},
|
|
20
|
+
evidence_records: [],
|
|
20
21
|
stdout_sha256: sha256Hex(""),
|
|
21
22
|
stderr_sha256: sha256Hex(""),
|
|
22
23
|
attempts: 0,
|
|
@@ -55,6 +56,7 @@ export async function executeCheckRunner(check, snapshotRoot) {
|
|
|
55
56
|
execution_status: "infrastructure_error",
|
|
56
57
|
exit_code: -1,
|
|
57
58
|
observations: {},
|
|
59
|
+
evidence_records: [],
|
|
58
60
|
stdout_sha256: sha256Hex(""),
|
|
59
61
|
stderr_sha256: sha256Hex(reason),
|
|
60
62
|
attempts: attempt,
|
|
@@ -1,6 +1,14 @@
|
|
|
1
|
-
import { array, fail, key, literal, object, parseEnvironmentRequirements, PROOF_SURFACES, repositoryCwd, repositoryFile, repositoryPatterns, string, strings, } from "./long-task-delivery-shape.js";
|
|
1
|
+
import { array, EVIDENCE_CAPABILITIES, fail, key, JOURNEY_ROLES, literal, object, parseEnvironmentRequirements, PROOF_SURFACES, repositoryCwd, repositoryFile, repositoryPatterns, string, strings, } from "./long-task-delivery-shape.js";
|
|
2
2
|
export function parseCheck(value, label) {
|
|
3
|
-
const row = object(value, label, [
|
|
3
|
+
const row = object(value, label, [
|
|
4
|
+
"key",
|
|
5
|
+
"journey_roles",
|
|
6
|
+
"execution_target",
|
|
7
|
+
"scenario",
|
|
8
|
+
"proof_surface",
|
|
9
|
+
"runner",
|
|
10
|
+
"verification_inputs",
|
|
11
|
+
], [
|
|
4
12
|
"input_paths",
|
|
5
13
|
"expected_output_paths",
|
|
6
14
|
"artifact_globs",
|
|
@@ -8,8 +16,19 @@ export function parseCheck(value, label) {
|
|
|
8
16
|
"negative_assertions",
|
|
9
17
|
"environment_requirements",
|
|
10
18
|
]);
|
|
19
|
+
const executionTarget = object(row.execution_target, `${label}.execution_target`, ["target_ref", "entrypoint"]);
|
|
20
|
+
const scenario = object(row.scenario, `${label}.scenario`, ["given", "when"]);
|
|
11
21
|
return {
|
|
12
22
|
key: key(row.key, `${label}.key`),
|
|
23
|
+
journey_roles: array(row.journey_roles, `${label}.journey_roles`).map((item, index) => literal(item, JOURNEY_ROLES, `${label}.journey_roles[${index}]`)),
|
|
24
|
+
execution_target: {
|
|
25
|
+
target_ref: key(executionTarget.target_ref, `${label}.execution_target.target_ref`),
|
|
26
|
+
entrypoint: literal(executionTarget.entrypoint, ["root", "internal"], `${label}.execution_target.entrypoint`),
|
|
27
|
+
},
|
|
28
|
+
scenario: {
|
|
29
|
+
given: parseScenarioSteps(scenario.given, `${label}.scenario.given`),
|
|
30
|
+
when: parseScenarioSteps(scenario.when, `${label}.scenario.when`),
|
|
31
|
+
},
|
|
13
32
|
proof_surface: literal(row.proof_surface, PROOF_SURFACES, `${label}.proof_surface`),
|
|
14
33
|
runner: parseRunner(row.runner, `${label}.runner`),
|
|
15
34
|
verification_inputs: repositoryPatterns(row.verification_inputs, `${label}.verification_inputs`),
|
|
@@ -70,7 +89,7 @@ function parseRunner(value, label) {
|
|
|
70
89
|
function parseAssertions(value, label) {
|
|
71
90
|
return array(value, label).map((item, index) => {
|
|
72
91
|
const itemLabel = `${label}[${index}]`;
|
|
73
|
-
const row = object(item, itemLabel, ["key", "claims", "observation", "operator"], ["criterion", "expected"]);
|
|
92
|
+
const row = object(item, itemLabel, ["key", "claims", "observation", "operator", "evidence_capabilities"], ["criterion", "expected"]);
|
|
74
93
|
const operator = literal(row.operator, [
|
|
75
94
|
"equals",
|
|
76
95
|
"not_equals",
|
|
@@ -103,6 +122,7 @@ function parseAssertions(value, label) {
|
|
|
103
122
|
: {}),
|
|
104
123
|
claims: strings(row.claims, `${itemLabel}.claims`),
|
|
105
124
|
observation: string(row.observation, `${itemLabel}.observation`),
|
|
125
|
+
evidence_capabilities: array(row.evidence_capabilities, `${itemLabel}.evidence_capabilities`).map((capability, capabilityIndex) => literal(capability, EVIDENCE_CAPABILITIES, `${itemLabel}.evidence_capabilities[${capabilityIndex}]`)),
|
|
106
126
|
operator,
|
|
107
127
|
};
|
|
108
128
|
return isBinaryAssertionOperator(operator)
|
|
@@ -113,6 +133,16 @@ function parseAssertions(value, label) {
|
|
|
113
133
|
};
|
|
114
134
|
});
|
|
115
135
|
}
|
|
136
|
+
function parseScenarioSteps(value, label) {
|
|
137
|
+
return array(value, label).map((item, index) => {
|
|
138
|
+
const itemLabel = `${label}[${index}]`;
|
|
139
|
+
const row = object(item, itemLabel, ["key", "statement"]);
|
|
140
|
+
return {
|
|
141
|
+
key: key(row.key, `${itemLabel}.key`),
|
|
142
|
+
statement: string(row.statement, `${itemLabel}.statement`),
|
|
143
|
+
};
|
|
144
|
+
});
|
|
145
|
+
}
|
|
116
146
|
function isBinaryAssertionOperator(operator) {
|
|
117
147
|
return !["exists", "truthy", "falsy"].includes(operator);
|
|
118
148
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { CompiledCheckV2, DeliveryContractV2, EffectiveRiskLevel } from "./long-task-delivery-types.js";
|
|
2
|
+
type Reporter = (message: string) => void;
|
|
3
|
+
export declare function semanticConformanceRequired(contract: DeliveryContractV2, _effectiveRisk?: EffectiveRiskLevel): boolean;
|
|
4
|
+
export declare function validateSemanticConformance(contract: DeliveryContractV2, effectiveRisk: EffectiveRiskLevel, compiledChecks: CompiledCheckV2[], report?: Reporter): void;
|
|
5
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export function semanticConformanceRequired(contract, _effectiveRisk) {
|
|
2
|
+
const productFamilies = new Set(contract.task.execution_targets
|
|
3
|
+
.filter((target) => contract.task.target_profile.required_target_refs.includes(target.key))
|
|
4
|
+
.map((target) => target.runtime_family));
|
|
5
|
+
return (contract.risk.facts.weak_observability.length > 0 &&
|
|
6
|
+
(productFamilies.size > 1 || contract.stages.length > 1));
|
|
7
|
+
}
|
|
8
|
+
export function validateSemanticConformance(contract, effectiveRisk, compiledChecks, report) {
|
|
9
|
+
const declared = contract.global.acceptance.checks.filter((check) => check.journey_roles.includes("conformance"));
|
|
10
|
+
if (semanticConformanceRequired(contract, effectiveRisk) &&
|
|
11
|
+
!declared.length) {
|
|
12
|
+
issue(report, "semantic_conformance_check_required", contract.task.id);
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
for (const check of declared) {
|
|
16
|
+
if (check.runner.effect !== "read_only")
|
|
17
|
+
issue(report, "conformance_check_must_be_read_only", check.key);
|
|
18
|
+
if (![...check.positive_assertions, ...check.negative_assertions].some((assertion) => assertion.evidence_capabilities.includes("target_runtime")))
|
|
19
|
+
issue(report, "conformance_target_runtime_evidence_required", check.key);
|
|
20
|
+
const compiled = compiledChecks.find((candidate) => candidate.outcome_key === null && candidate.key === check.key);
|
|
21
|
+
if (!compiled)
|
|
22
|
+
continue;
|
|
23
|
+
if (compiledChecks.some((candidate) => candidate.internal_id !== compiled.internal_id &&
|
|
24
|
+
candidate.outcome_key !== null &&
|
|
25
|
+
candidate.raw_execution_identity === compiled.raw_execution_identity))
|
|
26
|
+
issue(report, "conformance_raw_execution_must_be_independent", check.key);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function issue(report, code, detail) {
|
|
30
|
+
const message = `delivery_contract_invalid:${code}:${detail}`;
|
|
31
|
+
if (report)
|
|
32
|
+
report(message);
|
|
33
|
+
else
|
|
34
|
+
throw new Error(message);
|
|
35
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
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
|
+
import type { CheckExecutionTargetV2, DeliveryJourneyRoleV2, DeliveryScenarioV2, DeliveryStageV2, EvidenceCapabilityV2, ExecutionTargetV2, ExternalConfirmationKindV2, KeyedStatementV2, TargetProfileV2 } from "./long-task-semantic-contract-types.js";
|
|
3
4
|
export type SourceClaimDispositionV2 = {
|
|
4
5
|
type: "claim";
|
|
5
6
|
refs: string[];
|
|
@@ -28,10 +29,6 @@ export interface SourceClaimV2 {
|
|
|
28
29
|
statement: string;
|
|
29
30
|
disposition: SourceClaimDispositionV2;
|
|
30
31
|
}
|
|
31
|
-
export interface KeyedStatementV2 {
|
|
32
|
-
key: string;
|
|
33
|
-
statement: string;
|
|
34
|
-
}
|
|
35
32
|
export interface KeyedPathV2 {
|
|
36
33
|
key: string;
|
|
37
34
|
path: string;
|
|
@@ -40,6 +37,9 @@ export interface ExternalConfirmationV2 {
|
|
|
40
37
|
key: string;
|
|
41
38
|
description: string;
|
|
42
39
|
owner: string;
|
|
40
|
+
kind: ExternalConfirmationKindV2;
|
|
41
|
+
impact_claims: string[];
|
|
42
|
+
blocks_target: boolean;
|
|
43
43
|
}
|
|
44
44
|
export type ProofSurface = "ui_browser" | "runtime_behavior" | "api_contract" | "data_state" | "security_boundary" | "population_coverage" | "implementation_structure";
|
|
45
45
|
export type RunnerType = "package_script" | "project_binary" | "node_oracle" | "playwright_test";
|
|
@@ -51,6 +51,7 @@ interface DeliveryAssertionBaseV2 {
|
|
|
51
51
|
criterion?: string;
|
|
52
52
|
claims: string[];
|
|
53
53
|
observation: string;
|
|
54
|
+
evidence_capabilities: EvidenceCapabilityV2[];
|
|
54
55
|
}
|
|
55
56
|
export type DeliveryAssertionV2 = (DeliveryAssertionBaseV2 & {
|
|
56
57
|
operator: PresenceOrUnaryAssertionOperator;
|
|
@@ -86,6 +87,9 @@ export type EnvironmentRequirementV2 = {
|
|
|
86
87
|
};
|
|
87
88
|
export interface DeliveryCheckV2 {
|
|
88
89
|
key: string;
|
|
90
|
+
journey_roles: DeliveryJourneyRoleV2[];
|
|
91
|
+
execution_target: CheckExecutionTargetV2;
|
|
92
|
+
scenario: DeliveryScenarioV2;
|
|
89
93
|
proof_surface: ProofSurface;
|
|
90
94
|
runner: DeliveryRunnerV2;
|
|
91
95
|
verification_inputs: string[];
|
|
@@ -144,9 +148,12 @@ export interface PopulationRequirementV2 {
|
|
|
144
148
|
export interface DeliveryOutcomeV2 {
|
|
145
149
|
key: string;
|
|
146
150
|
title: string;
|
|
151
|
+
stage: string;
|
|
147
152
|
depends_on: string[];
|
|
148
153
|
product: {
|
|
149
154
|
observable_result: string;
|
|
155
|
+
success_path_required: boolean;
|
|
156
|
+
degradation_path_required: boolean;
|
|
150
157
|
owner: DeliveryOwnerV2;
|
|
151
158
|
requirements: DeliveryRequirementV2[];
|
|
152
159
|
owner_surfaces: string[];
|
|
@@ -174,11 +181,14 @@ export interface DeliveryContractV2 {
|
|
|
174
181
|
id: string;
|
|
175
182
|
title: string;
|
|
176
183
|
goal: string;
|
|
184
|
+
target_profile: TargetProfileV2;
|
|
185
|
+
execution_targets: ExecutionTargetV2[];
|
|
177
186
|
source_paths: string[];
|
|
178
187
|
context_refs: string[];
|
|
179
188
|
context_snapshot_mode: "referenced" | "full";
|
|
180
189
|
};
|
|
181
190
|
source_claims: SourceClaimV2[];
|
|
191
|
+
stages: DeliveryStageV2[];
|
|
182
192
|
risk: {
|
|
183
193
|
requested_level: RequestedRiskLevel;
|
|
184
194
|
facts: LongTaskRiskFacts;
|
|
@@ -114,6 +114,7 @@ export async function compileDeliveryContract(workdirInput, projectRootInput = p
|
|
|
114
114
|
task: contract.task,
|
|
115
115
|
risk: contract.risk,
|
|
116
116
|
source_claims: contract.source_claims,
|
|
117
|
+
stages: contract.stages,
|
|
117
118
|
global: {
|
|
118
119
|
product: contract.global.product,
|
|
119
120
|
technical: contract.global.technical,
|
|
@@ -5,8 +5,9 @@ import { validateDeliveryContractStructure } from "./long-task-delivery-validati
|
|
|
5
5
|
import { parseOutcome, parseOutcomeFragment, safeFragmentPath, } from "./long-task-outcome-parser.js";
|
|
6
6
|
import { assertProtectedRepositoryFile } from "./long-task-protected-files.js";
|
|
7
7
|
import { array, literal, object, parseSourceClaims, strings, } from "./long-task-delivery-shape.js";
|
|
8
|
-
import { parseGlobal, parseRisk, parseTask } from "./long-task-root-shape.js";
|
|
8
|
+
import { parseGlobal, parseRisk, parseStages, parseTask, } from "./long-task-root-shape.js";
|
|
9
9
|
import { repositoryRoot } from "./long-task-workspace.js";
|
|
10
|
+
import { assertNoSemanticDriftMigration, semanticDriftMigrationFields, } from "./long-task-semantic-drift-migration.js";
|
|
10
11
|
export const DELIVERY_CONTRACT_FILE = "delivery-contract.yaml";
|
|
11
12
|
export async function parseDeliveryContract(workdir) {
|
|
12
13
|
return (await parseDeliveryContractBundle(workdir)).contract;
|
|
@@ -75,7 +76,8 @@ function parseRoot(raw, bundle) {
|
|
|
75
76
|
decoded.schema_version ===
|
|
76
77
|
"long-task-delivery-v1")
|
|
77
78
|
throw new Error("long_task_delivery_v1_retired_use_v2");
|
|
78
|
-
|
|
79
|
+
assertNoSemanticDriftMigration(semanticDriftMigrationFields(decoded));
|
|
80
|
+
return object(decoded, "$", ["schema_version", "task", "source_claims", "stages", "risk", "global"], bundle ? ["outcomes", "outcome_files"] : ["outcomes"]);
|
|
79
81
|
}
|
|
80
82
|
function parseContractRoot(root, outcomes) {
|
|
81
83
|
literal(root.schema_version, ["long-task-delivery-v2"], "schema_version");
|
|
@@ -83,6 +85,7 @@ function parseContractRoot(root, outcomes) {
|
|
|
83
85
|
schema_version: "long-task-delivery-v2",
|
|
84
86
|
task: parseTask(root.task),
|
|
85
87
|
source_claims: parseSourceClaims(root.source_claims, "source_claims"),
|
|
88
|
+
stages: parseStages(root.stages),
|
|
86
89
|
risk: parseRisk(root.risk),
|
|
87
90
|
global: parseGlobal(root.global),
|
|
88
91
|
outcomes,
|
|
@@ -2,7 +2,9 @@ export * from "./long-task-contract-types.js";
|
|
|
2
2
|
export * from "./long-task-counterfactual-types.js";
|
|
3
3
|
export * from "./long-task-authority-types.js";
|
|
4
4
|
export * from "./long-task-evidence-adapter-types.js";
|
|
5
|
+
export * from "./long-task-evidence-capability-types.js";
|
|
5
6
|
export * from "./long-task-risk-types.js";
|
|
6
7
|
export * from "./long-task-runtime-types.js";
|
|
8
|
+
export * from "./long-task-semantic-contract-types.js";
|
|
7
9
|
export * from "./long-task-source-authority-types.js";
|
|
8
10
|
export * from "./long-task-workspace-runtime-types.js";
|
|
@@ -2,7 +2,9 @@ export * from "./long-task-contract-types.js";
|
|
|
2
2
|
export * from "./long-task-counterfactual-types.js";
|
|
3
3
|
export * from "./long-task-authority-types.js";
|
|
4
4
|
export * from "./long-task-evidence-adapter-types.js";
|
|
5
|
+
export * from "./long-task-evidence-capability-types.js";
|
|
5
6
|
export * from "./long-task-risk-types.js";
|
|
6
7
|
export * from "./long-task-runtime-types.js";
|
|
8
|
+
export * from "./long-task-semantic-contract-types.js";
|
|
7
9
|
export * from "./long-task-source-authority-types.js";
|
|
8
10
|
export * from "./long-task-workspace-runtime-types.js";
|
|
@@ -4,6 +4,9 @@ import { proveRepositoryPatternSubset } from "./long-task-paths.js";
|
|
|
4
4
|
import { validateSourceClaimMappings } from "./long-task-source-claim-validation.js";
|
|
5
5
|
import { validateDeclaredCheckSafety } from "./long-task-claim-proof-policy.js";
|
|
6
6
|
import { validateEvidenceAdapterCompatibility } from "./long-task-evidence-adapter-policy.js";
|
|
7
|
+
import { validateEvidenceCapabilityDeclarations } from "./long-task-evidence-capability-policy.js";
|
|
8
|
+
import { validateDeliveryStages } from "./long-task-stage-policy.js";
|
|
9
|
+
import { validateExecutionTargets, validateExternalConfirmationImpacts, } from "./long-task-target-policy.js";
|
|
7
10
|
export function validateDeliveryContractStructure(contract) {
|
|
8
11
|
validateUniqueKeys(contract);
|
|
9
12
|
validateDependencies(contract);
|
|
@@ -15,12 +18,19 @@ export function validateDeliveryContractStructure(contract) {
|
|
|
15
18
|
});
|
|
16
19
|
validateSourceClaimMappings(contract, claims);
|
|
17
20
|
assertCompiledClaimsCovered(claims);
|
|
21
|
+
validateDeliveryStages(contract);
|
|
22
|
+
validateExecutionTargets(contract);
|
|
23
|
+
validateEvidenceCapabilityDeclarations(contract);
|
|
24
|
+
validateExternalConfirmationImpacts(contract, claims);
|
|
18
25
|
}
|
|
19
26
|
export function deliveryContractStructureDiagnostics(contract) {
|
|
20
27
|
const diagnostics = [];
|
|
21
28
|
const report = (message) => diagnostics.push(message);
|
|
22
29
|
validateUniqueKeys(contract, report);
|
|
23
30
|
validateDependencies(contract, report);
|
|
31
|
+
validateDeliveryStages(contract, report);
|
|
32
|
+
validateExecutionTargets(contract, report);
|
|
33
|
+
validateEvidenceCapabilityDeclarations(contract, report);
|
|
24
34
|
validateOwnerAndBindings(contract, report);
|
|
25
35
|
validateDeclaredCheckSafety(contract, report);
|
|
26
36
|
validateEvidenceAdapters(contract, report);
|
|
@@ -30,6 +40,7 @@ export function deliveryContractStructureDiagnostics(contract) {
|
|
|
30
40
|
});
|
|
31
41
|
if (claims) {
|
|
32
42
|
validateSourceClaimMappings(contract, claims, report);
|
|
43
|
+
validateExternalConfirmationImpacts(contract, claims, report);
|
|
33
44
|
capture(diagnostics, () => assertCompiledClaimsCovered(claims));
|
|
34
45
|
}
|
|
35
46
|
return [...new Set(diagnostics)];
|