project-tiny-context-harness 0.8.1 → 0.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +401 -395
- package/assets/README.md +628 -549
- package/assets/README.zh-CN.md +345 -339
- package/assets/agents/.gitkeep +1 -1
- package/assets/agents/AGENTS_CORE.md +70 -70
- package/assets/context_templates/architecture.md +28 -28
- package/assets/context_templates/area.md +34 -34
- package/assets/context_templates/context.toml +30 -30
- package/assets/context_templates/deployment.md +35 -35
- package/assets/context_templates/global.md +57 -57
- package/assets/context_templates/product-surface-contract.md +70 -70
- package/assets/context_templates/screen-contract.md +189 -189
- package/assets/context_templates/verification.md +32 -32
- package/assets/github/.gitkeep +1 -1
- package/assets/github/harness.yml +39 -39
- package/assets/make/.gitkeep +1 -1
- package/assets/make/ty-context.mk +48 -48
- package/assets/skills/context_development_engineer/SKILL.md +137 -137
- package/assets/skills/context_full_project_export/SKILL.md +28 -28
- package/assets/skills/context_harness_upgrade/SKILL.md +60 -60
- package/assets/skills/context_product_plan/SKILL.md +88 -88
- package/assets/skills/context_surface_contract/SKILL.md +191 -191
- package/assets/skills/context_uiux_design/SKILL.md +172 -172
- package/assets/skills/design-resource-authoring/SKILL.md +85 -85
- package/assets/skills/design-resource-authoring/references/downstream-handoff.md +136 -136
- package/assets/skills/design-resource-authoring/references/open-design-provider.md +135 -135
- package/assets/skills/design-resource-authoring/references/resource-selection.md +173 -173
- package/assets/skills/design-system-authoring/SKILL.md +57 -57
- package/assets/skills/design-system-authoring/agents/openai.yaml +6 -6
- package/assets/skills/design-system-authoring/references/authority-adoption.md +48 -48
- package/assets/skills/design-system-authoring/references/open-design-design-system-provider.md +110 -110
- package/assets/skills/long-task-workflow/SKILL.md +100 -100
- package/assets/skills/long-task-workflow/references/authority-lifecycle.md +75 -73
- package/assets/skills/long-task-workflow/references/contract-authoring.md +119 -115
- package/assets/skills/long-task-workflow/references/evidence-design.md +77 -76
- package/assets/skills/long-task-workflow/references/source-authoring.md +102 -99
- package/assets/skills/source-plan-authoring/SKILL.md +14 -14
- package/assets/tools/validate_context.py +442 -442
- package/dist/commands/design-resource.js +2 -2
- package/dist/commands/index.js +26 -26
- package/dist/commands/long-task-authoring.js +83 -9
- package/dist/commands/long-task.js +15 -15
- package/dist/lib/context-graph-snapshot.js +7 -0
- package/dist/lib/design-resource-handoff-shape-evidence.js +3 -0
- package/dist/lib/design-resource-handoff-types.d.ts +2 -0
- package/dist/lib/design-resource-handoff-validation-coverage.js +1 -0
- package/dist/lib/design-resource-handoff-validation-structure.js +2 -0
- package/dist/lib/execution-target-capabilities.d.ts +2 -0
- package/dist/lib/execution-target-capabilities.js +31 -0
- package/dist/lib/long-task-acceptance-shape.js +81 -20
- package/dist/lib/long-task-applicability-shape.d.ts +4 -0
- package/dist/lib/long-task-applicability-shape.js +54 -0
- package/dist/lib/long-task-assertions-v2.js +8 -0
- package/dist/lib/long-task-authoring-preflight-diagnostics.js +5 -0
- package/dist/lib/long-task-authoring-preflight-repair-order.js +3 -0
- package/dist/lib/long-task-authoring-preflight.js +12 -8
- package/dist/lib/long-task-authority-materials.js +46 -4
- package/dist/lib/long-task-authority-policy.d.ts +54 -0
- package/dist/lib/long-task-authority-policy.js +61 -0
- package/dist/lib/long-task-authority-types.d.ts +12 -2
- package/dist/lib/long-task-authority.js +9 -2
- package/dist/lib/long-task-check-shape.js +6 -1
- package/dist/lib/long-task-claim-definitions.js +27 -42
- package/dist/lib/long-task-claims.js +275 -146
- package/dist/lib/long-task-contract-types.d.ts +42 -8
- package/dist/lib/long-task-control-fields.d.ts +12 -0
- package/dist/lib/long-task-control-fields.js +66 -0
- package/dist/lib/long-task-control-types.d.ts +1 -0
- package/dist/lib/long-task-control-types.js +1 -0
- package/dist/lib/long-task-counterfactual-claim-policy.js +7 -0
- package/dist/lib/long-task-counterfactual-types.d.ts +12 -0
- package/dist/lib/long-task-delivery-compiler.js +1 -0
- package/dist/lib/long-task-delivery-preflight.js +24 -0
- package/dist/lib/long-task-delivery-shape.d.ts +1 -0
- package/dist/lib/long-task-delivery-shape.js +1 -0
- package/dist/lib/long-task-delivery-types.d.ts +1 -0
- package/dist/lib/long-task-delivery-types.js +1 -0
- package/dist/lib/long-task-delivery-validation.js +46 -0
- package/dist/lib/long-task-design-resource-handoff.js +48 -7
- package/dist/lib/long-task-evidence-capability-codec.js +37 -0
- package/dist/lib/long-task-evidence-capability-policy.js +80 -38
- package/dist/lib/long-task-evidence-capability-runtime.js +36 -0
- package/dist/lib/long-task-evidence-capability-types.d.ts +13 -1
- package/dist/lib/long-task-evidence-findings.js +3 -0
- package/dist/lib/long-task-evidence-sensitivity-policy.js +38 -0
- package/dist/lib/long-task-evidence-v2.js +7 -1
- package/dist/lib/long-task-final-integrity.d.ts +16 -0
- package/dist/lib/long-task-final-integrity.js +98 -0
- package/dist/lib/long-task-final-v2.js +17 -34
- package/dist/lib/long-task-outcome-parser.js +22 -4
- package/dist/lib/long-task-playwright-case-evidence.d.ts +2 -0
- package/dist/lib/long-task-playwright-case-evidence.js +10 -2
- package/dist/lib/long-task-playwright-evidence.d.ts +1 -0
- package/dist/lib/long-task-playwright-evidence.js +32 -0
- package/dist/lib/long-task-product-shape.d.ts +3 -1
- package/dist/lib/long-task-product-shape.js +100 -4
- package/dist/lib/long-task-requirement-shape.js +3 -0
- package/dist/lib/long-task-root-shape.js +12 -6
- package/dist/lib/long-task-runner-freeze.js +16 -0
- package/dist/lib/long-task-runtime-types.d.ts +11 -2
- package/dist/lib/long-task-semantic-assurance-policy.d.ts +4 -0
- package/dist/lib/long-task-semantic-assurance-policy.js +52 -0
- package/dist/lib/long-task-semantic-contract-types.d.ts +18 -1
- package/dist/lib/long-task-semantic-drift-migration.js +33 -2
- package/dist/lib/long-task-semantic-mutation.d.ts +7 -0
- package/dist/lib/long-task-semantic-mutation.js +81 -0
- package/dist/lib/long-task-shape-primitives.d.ts +1 -1
- package/dist/lib/long-task-shape-primitives.js +1 -0
- package/dist/lib/long-task-source-authority-types.d.ts +2 -0
- package/dist/lib/long-task-source-item-parser.d.ts +1 -1
- package/dist/lib/long-task-source-item-parser.js +150 -104
- package/dist/lib/long-task-source-markers.d.ts +12 -0
- package/dist/lib/long-task-source-markers.js +146 -0
- package/dist/lib/long-task-source-target-continuity.d.ts +1 -1
- package/dist/lib/long-task-source-target-continuity.js +80 -55
- package/dist/lib/long-task-source-target-index.js +7 -29
- package/dist/lib/long-task-status-v2.d.ts +1 -0
- package/dist/lib/long-task-status-v2.js +2 -2
- package/dist/lib/long-task-target-policy.js +20 -0
- package/dist/lib/long-task-ui-design-policy.js +27 -1
- package/dist/lib/long-task-ui-surface-shape.js +21 -1
- package/dist/lib/long-task-ui-surface-types.d.ts +7 -0
- package/dist/lib/long-task-verification-preview.d.ts +10 -0
- package/dist/lib/long-task-verifier-dependency-closure.d.ts +3 -0
- package/dist/lib/long-task-verifier-dependency-closure.js +179 -0
- package/dist/lib/long-task-verifier-v2.js +12 -2
- package/dist/lib/long-task-workspace.js +5 -1
- package/dist/schemas/long-task-delivery-v2/long-task-delivery-v2.schema.json +99 -25
- package/migrations/README.md +15 -15
- package/package.json +84 -84
- package/source-mappings.yaml +25 -25
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { parseGlobalCounterfactuals } from "./long-task-acceptance-shape.js";
|
|
2
2
|
import { parseCheck } from "./long-task-check-shape.js";
|
|
3
|
-
import { array, boolean, key, literal, object,
|
|
3
|
+
import { array, boolean, key, literal, object, parseApplicableKeyedStatements, parseClaimApplicability, parseKeyedPaths, repositoryFiles, string, strings, } from "./long-task-delivery-shape.js";
|
|
4
|
+
import { EXECUTION_TARGET_CAPABILITIES } from "./execution-target-capabilities.js";
|
|
4
5
|
const RISK_FACTS = [
|
|
5
6
|
"public_api_or_schema_change",
|
|
6
7
|
"persistent_data_change",
|
|
@@ -51,6 +52,7 @@ export function parseTask(value) {
|
|
|
51
52
|
"role",
|
|
52
53
|
"runtime_family",
|
|
53
54
|
"root_entrypoint",
|
|
55
|
+
"capabilities",
|
|
54
56
|
]);
|
|
55
57
|
return {
|
|
56
58
|
key: key(target.key, `${label}.key`),
|
|
@@ -65,13 +67,14 @@ export function parseTask(value) {
|
|
|
65
67
|
"external",
|
|
66
68
|
], `${label}.runtime_family`),
|
|
67
69
|
root_entrypoint: string(target.root_entrypoint, `${label}.root_entrypoint`),
|
|
70
|
+
capabilities: strings(target.capabilities, `${label}.capabilities`).map((item, capabilityIndex) => literal(item, EXECUTION_TARGET_CAPABILITIES, `${label}.capabilities[${capabilityIndex}]`)),
|
|
68
71
|
};
|
|
69
72
|
}),
|
|
70
73
|
source_paths: repositoryFiles(row.source_paths, "task.source_paths"),
|
|
71
74
|
context_refs: repositoryFiles(row.context_refs, "task.context_refs"),
|
|
72
75
|
context_snapshot_mode: Object.hasOwn(row, "context_snapshot_mode")
|
|
73
76
|
? literal(row.context_snapshot_mode, ["referenced", "full"], "task.context_snapshot_mode")
|
|
74
|
-
: "
|
|
77
|
+
: "full",
|
|
75
78
|
};
|
|
76
79
|
}
|
|
77
80
|
export function parseStages(value) {
|
|
@@ -107,25 +110,28 @@ export function parseRisk(value) {
|
|
|
107
110
|
};
|
|
108
111
|
}
|
|
109
112
|
export function parseGlobal(value) {
|
|
110
|
-
const row = object(value, "global", [], ["product", "technical", "acceptance"]);
|
|
113
|
+
const row = object(value, "global", [], ["applicability", "product", "technical", "acceptance"]);
|
|
111
114
|
const product = object(Object.hasOwn(row, "product") ? row.product : {}, "global.product", [], ["non_goals"]);
|
|
112
115
|
const technical = object(Object.hasOwn(row, "technical") ? row.technical : {}, "global.technical", [], ["constraints", "forbidden_paths", "forbidden_shortcuts"]);
|
|
113
116
|
const acceptance = object(Object.hasOwn(row, "acceptance") ? row.acceptance : {}, "global.acceptance", [], ["checks", "counterfactual_controls", "external_confirmations"]);
|
|
114
117
|
return {
|
|
118
|
+
applicability: Object.hasOwn(row, "applicability")
|
|
119
|
+
? parseClaimApplicability(row.applicability, "global.applicability")
|
|
120
|
+
: [],
|
|
115
121
|
product: {
|
|
116
122
|
non_goals: Object.hasOwn(product, "non_goals")
|
|
117
|
-
?
|
|
123
|
+
? parseApplicableKeyedStatements(product.non_goals, "global.product.non_goals")
|
|
118
124
|
: [],
|
|
119
125
|
},
|
|
120
126
|
technical: {
|
|
121
127
|
constraints: Object.hasOwn(technical, "constraints")
|
|
122
|
-
?
|
|
128
|
+
? parseApplicableKeyedStatements(technical.constraints, "global.technical.constraints")
|
|
123
129
|
: [],
|
|
124
130
|
forbidden_paths: Object.hasOwn(technical, "forbidden_paths")
|
|
125
131
|
? parseKeyedPaths(technical.forbidden_paths, "global.technical.forbidden_paths")
|
|
126
132
|
: [],
|
|
127
133
|
forbidden_shortcuts: Object.hasOwn(technical, "forbidden_shortcuts")
|
|
128
|
-
?
|
|
134
|
+
? parseApplicableKeyedStatements(technical.forbidden_shortcuts, "global.technical.forbidden_shortcuts")
|
|
129
135
|
: [],
|
|
130
136
|
},
|
|
131
137
|
acceptance: {
|
|
@@ -7,6 +7,7 @@ import { nearestRunnerFile, npmCliPath, npxCliPath, } from "./long-task-runner-f
|
|
|
7
7
|
import { canonicalValueJson, sha256Hex } from "./strict-codec.js";
|
|
8
8
|
import { repoRelative, resolveInsideRepository, } from "./long-task-workspace.js";
|
|
9
9
|
import { evidenceAdapterForRunner } from "./long-task-evidence-adapter-policy.js";
|
|
10
|
+
import { freezeLocalVerifierDependencyClosure, packageScriptVerifierRoots, } from "./long-task-verifier-dependency-closure.js";
|
|
10
11
|
export async function freezeDeliveryCheck(check, outcomeKey, repository, baseline, executionTarget, knownExecutionTargets, designConformanceTargets) {
|
|
11
12
|
const prefix = outcomeKey ? `CHECK.${outcomeKey}` : "CHECK.GLOBAL";
|
|
12
13
|
const expectedOutputs = check.expected_output_paths.map((pattern, index) => assertRepositoryPattern(repository, pattern, `${check.key}.expected_output_paths[${index}]`));
|
|
@@ -164,6 +165,21 @@ async function freezeVerificationInputs(check, repository, manifest, cwd, target
|
|
|
164
165
|
const protectedFile = await assertProtectedRepositoryFile(repository, path.join(repository, ...relative.split("/")), `${check.key}.automatic_verification_input`);
|
|
165
166
|
result[relative] = sha256Hex(await readFile(protectedFile));
|
|
166
167
|
}
|
|
168
|
+
if (check.runner.type === "package_script") {
|
|
169
|
+
const packageJson = JSON.parse(await readFile(target, "utf8"));
|
|
170
|
+
const script = packageJson.scripts?.[check.runner.target];
|
|
171
|
+
if (typeof script !== "string" || !script.trim())
|
|
172
|
+
throw new Error(`package_script_not_found:${check.key}:${check.runner.target}`);
|
|
173
|
+
for (const relative of packageScriptVerifierRoots(script, repoRelative(repository, target), manifest)) {
|
|
174
|
+
const protectedFile = await assertProtectedRepositoryFile(repository, path.join(repository, ...relative.split("/")), `${check.key}.package_script_entry`);
|
|
175
|
+
result[relative] = sha256Hex(await readFile(protectedFile));
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
Object.assign(result, await freezeLocalVerifierDependencyClosure(repository, Object.keys(result), manifest, [
|
|
179
|
+
...check.input_paths,
|
|
180
|
+
...check.expected_output_paths,
|
|
181
|
+
...check.artifact_globs,
|
|
182
|
+
]));
|
|
167
183
|
return sortRecord(result);
|
|
168
184
|
}
|
|
169
185
|
function sortRecord(value) {
|
|
@@ -32,20 +32,24 @@ export interface ProductClaimV2 {
|
|
|
32
32
|
id: string;
|
|
33
33
|
outcome_key: string;
|
|
34
34
|
local_key: string;
|
|
35
|
-
kind: "result" | "requirement" | "control" | "non_completing" | "obligation" | "forbidden_shortcut";
|
|
35
|
+
kind: "result" | "requirement" | "control" | "control_relation" | "non_completing" | "obligation" | "forbidden_shortcut";
|
|
36
36
|
required_proof_surfaces: ProofSurface[];
|
|
37
|
+
required_polarity: "positive" | "negative";
|
|
38
|
+
applicability_refs: string[];
|
|
37
39
|
}
|
|
38
40
|
export interface GlobalClaimV2 {
|
|
39
41
|
id: string;
|
|
40
42
|
local_key: string;
|
|
41
43
|
kind: "global_non_goal" | "global_constraint" | "global_forbidden_shortcut";
|
|
42
|
-
required_polarity: "
|
|
44
|
+
required_polarity: "positive" | "negative";
|
|
45
|
+
applicability_refs: string[];
|
|
43
46
|
}
|
|
44
47
|
export interface ClaimProofV2 {
|
|
45
48
|
check_key: string;
|
|
46
49
|
assertion_key: string | null;
|
|
47
50
|
polarity: "positive" | "negative" | "population" | "counterfactual";
|
|
48
51
|
proof_surface: ProofSurface;
|
|
52
|
+
applicability_ref: string | null;
|
|
49
53
|
}
|
|
50
54
|
export interface ClaimCoverageSummaryV2 {
|
|
51
55
|
claims_total: number;
|
|
@@ -53,6 +57,8 @@ export interface ClaimCoverageSummaryV2 {
|
|
|
53
57
|
uncovered_claims: string[];
|
|
54
58
|
claims_by_global: Record<string, {
|
|
55
59
|
covered: boolean;
|
|
60
|
+
applicability_refs: string[];
|
|
61
|
+
uncovered_applicability_refs: string[];
|
|
56
62
|
proofs: ClaimProofV2[];
|
|
57
63
|
}>;
|
|
58
64
|
claims_by_outcome: Record<string, Record<string, {
|
|
@@ -60,6 +66,8 @@ export interface ClaimCoverageSummaryV2 {
|
|
|
60
66
|
covered_surfaces: ProofSurface[];
|
|
61
67
|
missing_surfaces: ProofSurface[];
|
|
62
68
|
covered: boolean;
|
|
69
|
+
applicability_refs: string[];
|
|
70
|
+
uncovered_applicability_refs: string[];
|
|
63
71
|
proofs: ClaimProofV2[];
|
|
64
72
|
}>>;
|
|
65
73
|
}
|
|
@@ -129,6 +137,7 @@ export interface AssertionResultV2 {
|
|
|
129
137
|
polarity: "positive" | "negative";
|
|
130
138
|
passed: boolean;
|
|
131
139
|
claims: string[];
|
|
140
|
+
applicability_ref?: string;
|
|
132
141
|
observation: string;
|
|
133
142
|
evidence_capabilities: EvidenceCapabilityV2[];
|
|
134
143
|
evidence_complete: boolean;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export function validateSemanticAssuranceShape(contract, report) {
|
|
2
|
+
if (contract.task.context_snapshot_mode !== "full")
|
|
3
|
+
issue(report, "long_task_full_context_required", contract.task.context_snapshot_mode);
|
|
4
|
+
validateApplicabilityScope("GLOBAL", contract.global.applicability, report);
|
|
5
|
+
for (const outcome of contract.outcomes)
|
|
6
|
+
validateApplicabilityScope(outcome.key, outcome.applicability, report);
|
|
7
|
+
}
|
|
8
|
+
function validateApplicabilityScope(scope, profiles, report) {
|
|
9
|
+
if (!profiles.length)
|
|
10
|
+
return;
|
|
11
|
+
let expectedDimensionKeys = null;
|
|
12
|
+
const cells = new Map();
|
|
13
|
+
for (const profile of profiles) {
|
|
14
|
+
if (!profile.dimensions.length)
|
|
15
|
+
issue(report, "applicability_dimensions_required", `${scope}:${profile.key}`);
|
|
16
|
+
const keys = profile.dimensions.map((dimension) => dimension.key);
|
|
17
|
+
if (new Set(keys).size !== keys.length)
|
|
18
|
+
issue(report, "applicability_dimension_duplicate", `${scope}:${profile.key}`);
|
|
19
|
+
const sortedKeys = [...keys].sort();
|
|
20
|
+
if (expectedDimensionKeys === null)
|
|
21
|
+
expectedDimensionKeys = sortedKeys;
|
|
22
|
+
else if (!same(expectedDimensionKeys, sortedKeys))
|
|
23
|
+
issue(report, "applicability_dimension_set_mismatch", `${scope}:${profile.key}:${expectedDimensionKeys.join(",")}:${sortedKeys.join(",")}`);
|
|
24
|
+
const dimensions = [...profile.dimensions]
|
|
25
|
+
.sort((left, right) => left.key.localeCompare(right.key))
|
|
26
|
+
.map((dimension) => `${dimension.key}=${dimension.value}`)
|
|
27
|
+
.join(",");
|
|
28
|
+
const cell = [
|
|
29
|
+
profile.target_ref,
|
|
30
|
+
profile.journey_role,
|
|
31
|
+
dimensions,
|
|
32
|
+
[...profile.given_refs].sort().join(","),
|
|
33
|
+
profile.when_refs.join(","),
|
|
34
|
+
].join("|");
|
|
35
|
+
const owner = cells.get(cell);
|
|
36
|
+
if (owner)
|
|
37
|
+
issue(report, "applicability_cell_duplicate", `${scope}:${profile.key}:${owner}`);
|
|
38
|
+
else
|
|
39
|
+
cells.set(cell, profile.key);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function same(left, right) {
|
|
43
|
+
return (left.length === right.length &&
|
|
44
|
+
left.every((value, index) => value === right[index]));
|
|
45
|
+
}
|
|
46
|
+
function issue(report, code, detail) {
|
|
47
|
+
const message = `delivery_contract_invalid:${code}:${detail}`;
|
|
48
|
+
if (report)
|
|
49
|
+
report(message);
|
|
50
|
+
else
|
|
51
|
+
throw new Error(message);
|
|
52
|
+
}
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
+
import type { ExecutionTargetCapabilityV2 } from "./execution-target-capabilities.js";
|
|
2
|
+
export type { ExecutionTargetCapabilityV2 } from "./execution-target-capabilities.js";
|
|
1
3
|
export interface KeyedStatementV2 {
|
|
2
4
|
key: string;
|
|
3
5
|
statement: string;
|
|
4
6
|
}
|
|
7
|
+
export interface ApplicableKeyedStatementV2 extends KeyedStatementV2 {
|
|
8
|
+
applicability_refs: string[];
|
|
9
|
+
}
|
|
5
10
|
export type ExternalConfirmationKindV2 = "functional_prerequisite" | "field_validation" | "production_release_gate" | "commercial_activation" | "expert_authority";
|
|
6
11
|
export type TargetCompletionStateV2 = "implementation_complete" | "target_profile_usable" | "production_release_ready";
|
|
7
12
|
export type ExecutionTargetRuntimeFamilyV2 = "browser" | "native" | "desktop" | "service" | "process" | "external";
|
|
@@ -17,6 +22,7 @@ export interface ExecutionTargetV2 {
|
|
|
17
22
|
role: "product" | "support" | "observer";
|
|
18
23
|
runtime_family: ExecutionTargetRuntimeFamilyV2;
|
|
19
24
|
root_entrypoint: string;
|
|
25
|
+
capabilities: ExecutionTargetCapabilityV2[];
|
|
20
26
|
}
|
|
21
27
|
export interface DeliveryStageV2 {
|
|
22
28
|
key: string;
|
|
@@ -25,7 +31,18 @@ export interface DeliveryStageV2 {
|
|
|
25
31
|
gate_outcome: string;
|
|
26
32
|
}
|
|
27
33
|
export type DeliveryJourneyRoleV2 = "success" | "degradation" | "recovery" | "stage_gate" | "conformance";
|
|
28
|
-
export
|
|
34
|
+
export interface ClaimApplicabilityV2 {
|
|
35
|
+
key: string;
|
|
36
|
+
target_ref: string;
|
|
37
|
+
journey_role: DeliveryJourneyRoleV2;
|
|
38
|
+
dimensions: Array<{
|
|
39
|
+
key: string;
|
|
40
|
+
value: string;
|
|
41
|
+
}>;
|
|
42
|
+
given_refs: string[];
|
|
43
|
+
when_refs: string[];
|
|
44
|
+
}
|
|
45
|
+
export type EvidenceCapabilityV2 = "presence" | "interaction_trace" | "state_delta" | "cross_surface_consistency" | "durable_readback" | "boundary_invocation" | "external_side_effect" | "failure_injection" | "visual_render" | "design_conformance" | "design_method" | "target_runtime" | "input_variation";
|
|
29
46
|
export interface CheckExecutionTargetV2 {
|
|
30
47
|
target_ref: string;
|
|
31
48
|
entrypoint: "root" | "internal";
|
|
@@ -6,7 +6,12 @@ export function semanticDriftMigrationFields(value) {
|
|
|
6
6
|
required(root, "$", ["stages"], missing);
|
|
7
7
|
const task = row(root.task);
|
|
8
8
|
if (task) {
|
|
9
|
-
required(task, "task", ["target_profile", "execution_targets"], missing);
|
|
9
|
+
required(task, "task", ["target_profile", "execution_targets", "context_snapshot_mode"], missing);
|
|
10
|
+
if (Object.hasOwn(task, "context_snapshot_mode") &&
|
|
11
|
+
task.context_snapshot_mode !== "full")
|
|
12
|
+
missing.push("task.context_snapshot_mode=full");
|
|
13
|
+
for (const [index, target] of rows(task.execution_targets).entries())
|
|
14
|
+
required(target, `task.execution_targets[${index}]`, ["capabilities"], missing);
|
|
10
15
|
const profile = row(task.target_profile);
|
|
11
16
|
if (profile)
|
|
12
17
|
required(profile, "task.target_profile", ["required_target_refs"], missing);
|
|
@@ -14,6 +19,7 @@ export function semanticDriftMigrationFields(value) {
|
|
|
14
19
|
for (const [index, outcome] of rows(root.outcomes).entries())
|
|
15
20
|
collectOutcome(outcome, `outcomes[${index}]`, missing);
|
|
16
21
|
const global = row(root.global);
|
|
22
|
+
collectApplicability(global?.applicability, "global.applicability", missing);
|
|
17
23
|
const globalAcceptance = row(global?.acceptance);
|
|
18
24
|
collectChecks(globalAcceptance?.checks, "global.acceptance.checks", missing);
|
|
19
25
|
for (const [index, confirmation] of rows(globalAcceptance?.external_confirmations).entries())
|
|
@@ -35,7 +41,8 @@ export function assertNoSemanticDriftMigration(fields) {
|
|
|
35
41
|
throw new Error(`long_task_delivery_v2_semantic_drift_migration_required:${detail}${suffix}`);
|
|
36
42
|
}
|
|
37
43
|
function collectOutcome(outcome, label, missing) {
|
|
38
|
-
required(outcome, label, ["stage"], missing);
|
|
44
|
+
required(outcome, label, ["stage", "applicability"], missing);
|
|
45
|
+
collectApplicability(outcome.applicability, `${label}.applicability`, missing);
|
|
39
46
|
const product = row(outcome.product);
|
|
40
47
|
if (product) {
|
|
41
48
|
required(product, `${label}.product`, ["success_path_required", "degradation_path_required"], missing);
|
|
@@ -43,9 +50,33 @@ function collectOutcome(outcome, label, missing) {
|
|
|
43
50
|
product.controls.length > 0 &&
|
|
44
51
|
!Object.hasOwn(product, "surface_bindings"))
|
|
45
52
|
missing.push(`${label}.product.surface_bindings`);
|
|
53
|
+
const relationClosure = row(product.control_relation_closure);
|
|
54
|
+
if (relationClosure && relationClosure.state !== "unresolved")
|
|
55
|
+
required(relationClosure, `${label}.product.control_relation_closure`, ["applicability_refs"], missing);
|
|
46
56
|
}
|
|
47
57
|
const acceptance = row(outcome.acceptance);
|
|
48
58
|
collectChecks(acceptance?.checks, `${label}.acceptance.checks`, missing);
|
|
59
|
+
const population = row(acceptance?.population);
|
|
60
|
+
if (population) {
|
|
61
|
+
required(population, `${label}.acceptance.population`, ["universe_binding_key"], missing);
|
|
62
|
+
const observations = row(population.observations);
|
|
63
|
+
if (observations)
|
|
64
|
+
required(observations, `${label}.acceptance.population.observations`, ["universe_ids"], missing);
|
|
65
|
+
}
|
|
66
|
+
for (const [bindingIndex, binding] of rows(product?.surface_bindings).entries()) {
|
|
67
|
+
for (const [blockerIndex, blocker] of rows(binding.acceptance_blockers).entries())
|
|
68
|
+
required(blocker, `${label}.product.surface_bindings[${bindingIndex}].acceptance_blockers[${blockerIndex}]`, ["required_capabilities"], missing);
|
|
69
|
+
for (const [targetIndex, target] of rows(binding.design_targets).entries())
|
|
70
|
+
for (const [methodIndex, method] of rows(target.verification_method_bindings).entries()) {
|
|
71
|
+
required(method, `${label}.product.surface_bindings[${bindingIndex}].design_targets[${targetIndex}].verification_method_bindings[${methodIndex}]`, ["evidence_artifacts"], missing);
|
|
72
|
+
for (const [artifactIndex, artifact] of rows(method.evidence_artifacts).entries())
|
|
73
|
+
required(artifact, `${label}.product.surface_bindings[${bindingIndex}].design_targets[${targetIndex}].verification_method_bindings[${methodIndex}].evidence_artifacts[${artifactIndex}]`, ["observation_path"], missing);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function collectApplicability(value, label, missing) {
|
|
78
|
+
for (const [index, profile] of rows(value).entries())
|
|
79
|
+
required(profile, `${label}[${index}]`, ["dimensions"], missing);
|
|
49
80
|
}
|
|
50
81
|
function collectChecks(value, label, missing) {
|
|
51
82
|
for (const [index, check] of rows(value).entries()) {
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { CounterfactualMutationV2 } from "./long-task-delivery-types.js";
|
|
2
|
+
type NarrowMutation = Extract<CounterfactualMutationV2, {
|
|
3
|
+
type: "replace_json_value" | "replace_text";
|
|
4
|
+
}>;
|
|
5
|
+
export declare function applyNarrowSemanticMutation(root: string, mutation: NarrowMutation): Promise<void>;
|
|
6
|
+
export declare function mutateSemanticText(current: string, mutation: NarrowMutation, requireChange?: boolean): string;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { canonicalValueJson } from "./strict-codec.js";
|
|
4
|
+
export async function applyNarrowSemanticMutation(root, mutation) {
|
|
5
|
+
const target = path.join(root, ...mutation.path.split("/"));
|
|
6
|
+
const current = await readFile(target, "utf8");
|
|
7
|
+
const next = mutateSemanticText(current, mutation, false);
|
|
8
|
+
await writeFile(target, next, "utf8");
|
|
9
|
+
}
|
|
10
|
+
export function mutateSemanticText(current, mutation, requireChange = true) {
|
|
11
|
+
if (mutation.type === "replace_text") {
|
|
12
|
+
if (requireChange && mutation.match === mutation.replacement)
|
|
13
|
+
throw new Error("counterfactual_replacement_must_change_carrier");
|
|
14
|
+
const count = occurrences(current, mutation.match);
|
|
15
|
+
if (count !== 1)
|
|
16
|
+
throw new Error(`counterfactual_text_match_count:${count}`);
|
|
17
|
+
return current.replace(mutation.match, mutation.replacement);
|
|
18
|
+
}
|
|
19
|
+
let value;
|
|
20
|
+
try {
|
|
21
|
+
value = JSON.parse(current);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
throw new Error("counterfactual_json_invalid");
|
|
25
|
+
}
|
|
26
|
+
const segments = mutation.pointer
|
|
27
|
+
.slice(1)
|
|
28
|
+
.split("/")
|
|
29
|
+
.map((segment) => segment.replace(/~1/gu, "/").replace(/~0/gu, "~"));
|
|
30
|
+
let owner = value;
|
|
31
|
+
for (const segment of segments.slice(0, -1))
|
|
32
|
+
owner = child(owner, segment, mutation.pointer);
|
|
33
|
+
const leaf = segments.at(-1);
|
|
34
|
+
if (!owner || typeof owner !== "object")
|
|
35
|
+
throw new Error(`counterfactual_json_pointer_unknown:${mutation.pointer}`);
|
|
36
|
+
if (Array.isArray(owner)) {
|
|
37
|
+
const index = arrayIndex(leaf, owner.length, mutation.pointer);
|
|
38
|
+
if (requireChange &&
|
|
39
|
+
canonicalValueJson(owner[index]) === canonicalValueJson(mutation.value))
|
|
40
|
+
throw new Error("counterfactual_replacement_must_change_carrier");
|
|
41
|
+
owner[index] = mutation.value;
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
const record = owner;
|
|
45
|
+
if (!Object.hasOwn(record, leaf))
|
|
46
|
+
throw new Error(`counterfactual_json_pointer_unknown:${mutation.pointer}`);
|
|
47
|
+
if (requireChange &&
|
|
48
|
+
canonicalValueJson(record[leaf]) === canonicalValueJson(mutation.value))
|
|
49
|
+
throw new Error("counterfactual_replacement_must_change_carrier");
|
|
50
|
+
record[leaf] = mutation.value;
|
|
51
|
+
}
|
|
52
|
+
return `${JSON.stringify(value, null, 2)}\n`;
|
|
53
|
+
}
|
|
54
|
+
function child(value, segment, pointer) {
|
|
55
|
+
if (!value || typeof value !== "object")
|
|
56
|
+
throw new Error(`counterfactual_json_pointer_unknown:${pointer}`);
|
|
57
|
+
if (Array.isArray(value))
|
|
58
|
+
return value[arrayIndex(segment, value.length, pointer)];
|
|
59
|
+
if (!Object.hasOwn(value, segment))
|
|
60
|
+
throw new Error(`counterfactual_json_pointer_unknown:${pointer}`);
|
|
61
|
+
return value[segment];
|
|
62
|
+
}
|
|
63
|
+
function arrayIndex(value, length, pointer) {
|
|
64
|
+
if (!/^(?:0|[1-9][0-9]*)$/u.test(value))
|
|
65
|
+
throw new Error(`counterfactual_json_pointer_unknown:${pointer}`);
|
|
66
|
+
const index = Number(value);
|
|
67
|
+
if (!Number.isSafeInteger(index) || index >= length)
|
|
68
|
+
throw new Error(`counterfactual_json_pointer_unknown:${pointer}`);
|
|
69
|
+
return index;
|
|
70
|
+
}
|
|
71
|
+
function occurrences(value, search) {
|
|
72
|
+
let count = 0;
|
|
73
|
+
let offset = 0;
|
|
74
|
+
while (true) {
|
|
75
|
+
const index = value.indexOf(search, offset);
|
|
76
|
+
if (index < 0)
|
|
77
|
+
return count;
|
|
78
|
+
count += 1;
|
|
79
|
+
offset = index + search.length;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -16,5 +16,5 @@ export declare function key(value: unknown, label: string): string;
|
|
|
16
16
|
export declare function nullable<T>(value: unknown, parser: (value: unknown) => T): T | null;
|
|
17
17
|
export declare const PROOF_SURFACES: readonly ["ui_browser", "runtime_behavior", "api_contract", "data_state", "security_boundary", "population_coverage", "implementation_structure"];
|
|
18
18
|
export declare const JOURNEY_ROLES: readonly ["success", "degradation", "recovery", "stage_gate", "conformance"];
|
|
19
|
-
export declare const EVIDENCE_CAPABILITIES: readonly ["presence", "interaction_trace", "state_delta", "cross_surface_consistency", "durable_readback", "boundary_invocation", "external_side_effect", "failure_injection", "visual_render", "design_conformance", "target_runtime", "input_variation"];
|
|
19
|
+
export declare const EVIDENCE_CAPABILITIES: readonly ["presence", "interaction_trace", "state_delta", "cross_surface_consistency", "durable_readback", "boundary_invocation", "external_side_effect", "failure_injection", "visual_render", "design_conformance", "design_method", "target_runtime", "input_variation"];
|
|
20
20
|
export declare function fail(label: string, message: string): never;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import type { RiskFactName } from "./long-task-risk-types.js";
|
|
2
2
|
export type SourceItemKind = "outcome_result" | "requirement" | "control" | "acceptance" | "technical_obligation" | "non_completing" | "non_goal" | "forbidden_shortcut" | "risk_fact" | "external_confirmation" | "decision";
|
|
3
|
+
export type SourceItemAspect = "architecture";
|
|
3
4
|
export interface CompiledSourceItemV2 {
|
|
4
5
|
key: string;
|
|
5
6
|
kind: SourceItemKind;
|
|
7
|
+
aspect?: SourceItemAspect;
|
|
6
8
|
source_path: string;
|
|
7
9
|
normalized_text: string;
|
|
8
10
|
text_sha256: string;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { CompiledSourceItemV2 } from "./long-task-delivery-types.js";
|
|
2
2
|
export declare function parseSourceItems(sourcePath: string, content: string): CompiledSourceItemV2[];
|
|
3
|
-
export
|
|
3
|
+
export { normalizeSourceItemText } from "./long-task-source-markers.js";
|