project-tiny-context-harness 0.8.16 → 0.8.17
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 +31 -16
- package/assets/README.md +31 -16
- package/assets/README.zh-CN.md +29 -14
- package/assets/context_templates/screen-contract.md +16 -0
- package/assets/skills/context_development_engineer/SKILL.md +16 -30
- package/assets/skills/context_development_engineer/references/engineering-design-reasoning.md +93 -0
- package/assets/skills/context_surface_contract/SKILL.md +13 -2
- package/assets/skills/context_uiux_design/SKILL.md +7 -3
- package/assets/skills/context_uiux_design/references/task-uiux-analysis.md +82 -0
- package/assets/skills/design-resource-authoring/SKILL.md +14 -8
- package/assets/skills/design-resource-authoring/references/downstream-handoff.md +18 -6
- package/assets/skills/design-resource-authoring/references/formal-selected-web-app-handoff.md +26 -8
- package/assets/skills/design-resource-authoring/references/implementation-feasibility.md +111 -0
- package/assets/skills/design-resource-authoring/references/open-design-provider.md +45 -7
- package/assets/skills/design-resource-authoring/references/recovery-and-writeback.md +7 -1
- package/assets/skills/design-resource-authoring/references/resource-selection.md +115 -3
- package/dist/commands/design-resource.js +9 -2
- package/dist/index.d.ts +1 -1
- package/dist/lib/design-resource-handoff-bundle.js +5 -0
- package/dist/lib/design-resource-handoff-input-types.d.ts +1 -1
- package/dist/lib/design-resource-handoff-manifest-projection.js +1 -0
- package/dist/lib/design-resource-handoff-set-integrity.js +1 -0
- package/dist/lib/design-resource-handoff-shape.js +6 -2
- package/dist/lib/design-resource-handoff-types.d.ts +5 -0
- package/dist/lib/design-resource-handoff-validation.js +12 -0
- package/dist/lib/design-resource-implementation-feasibility-model.d.ts +35 -0
- package/dist/lib/design-resource-implementation-feasibility-model.js +62 -0
- package/dist/lib/design-resource-implementation-feasibility-shape-sections.d.ts +43 -0
- package/dist/lib/design-resource-implementation-feasibility-shape-sections.js +142 -0
- package/dist/lib/design-resource-implementation-feasibility-shape.d.ts +4 -0
- package/dist/lib/design-resource-implementation-feasibility-shape.js +154 -0
- package/dist/lib/design-resource-implementation-feasibility-source-decision-projection.d.ts +24 -0
- package/dist/lib/design-resource-implementation-feasibility-source-decision-projection.js +106 -0
- package/dist/lib/design-resource-implementation-feasibility-source-decision.d.ts +21 -0
- package/dist/lib/design-resource-implementation-feasibility-source-decision.js +75 -0
- package/dist/lib/design-resource-implementation-feasibility-types.d.ts +135 -0
- package/dist/lib/design-resource-implementation-feasibility-types.js +37 -0
- package/dist/lib/design-resource-implementation-feasibility-validation-cells.d.ts +5 -0
- package/dist/lib/design-resource-implementation-feasibility-validation-cells.js +125 -0
- package/dist/lib/design-resource-implementation-feasibility-validation-document.d.ts +4 -0
- package/dist/lib/design-resource-implementation-feasibility-validation-document.js +167 -0
- package/dist/lib/design-resource-implementation-feasibility-validation-facts.d.ts +3 -0
- package/dist/lib/design-resource-implementation-feasibility-validation-facts.js +76 -0
- package/dist/lib/design-resource-implementation-feasibility-validation-realizations.d.ts +8 -0
- package/dist/lib/design-resource-implementation-feasibility-validation-realizations.js +76 -0
- package/dist/lib/design-resource-implementation-feasibility-validation-support.d.ts +10 -0
- package/dist/lib/design-resource-implementation-feasibility-validation-support.js +75 -0
- package/dist/lib/design-resource-implementation-feasibility-validation.d.ts +3 -0
- package/dist/lib/design-resource-implementation-feasibility-validation.js +138 -0
- package/dist/lib/design-resource-symbolic-fact-shape.js +3 -1
- package/dist/lib/design-resource-symbolic-fact-types.d.ts +5 -0
- package/dist/lib/design-resource-symbolic-fact-validation.js +13 -0
- package/dist/lib/long-task-activation-validation.js +77 -7
- package/dist/lib/long-task-check-runner.js +3 -296
- package/dist/lib/long-task-command-process.d.ts +9 -0
- package/dist/lib/long-task-command-process.js +175 -0
- package/dist/lib/long-task-delivery-validation.d.ts +5 -2
- package/dist/lib/long-task-delivery-validation.js +4 -4
- package/dist/lib/long-task-design-feasibility-binding-owners.d.ts +6 -0
- package/dist/lib/long-task-design-feasibility-binding-owners.js +52 -0
- package/dist/lib/long-task-design-feasibility-binding.d.ts +13 -0
- package/dist/lib/long-task-design-feasibility-binding.js +114 -0
- package/dist/lib/long-task-design-feasibility-source-closure.d.ts +11 -0
- package/dist/lib/long-task-design-feasibility-source-closure.js +78 -0
- package/dist/lib/long-task-design-resource-handoff.d.ts +3 -3
- package/dist/lib/long-task-design-resource-handoff.js +39 -3
- package/dist/lib/long-task-design-resource-method-binding.js +8 -2
- package/dist/lib/long-task-freshness.js +1 -1
- package/dist/lib/long-task-process-table.d.ts +12 -0
- package/dist/lib/long-task-process-table.js +119 -0
- package/dist/lib/long-task-process-tree.d.ts +9 -0
- package/dist/lib/long-task-process-tree.js +138 -0
- package/dist/lib/long-task-protected-files.d.ts +1 -1
- package/dist/lib/long-task-protected-files.js +1 -1
- package/dist/lib/long-task-ui-surface-policy.d.ts +2 -1
- package/dist/lib/long-task-ui-surface-policy.js +7 -4
- package/dist/lib/long-task-ui-surface-validation.d.ts +3 -1
- package/dist/lib/long-task-ui-surface-validation.js +2 -2
- package/dist/lib/repository-path-safety.d.ts +2 -0
- package/dist/lib/repository-path-safety.js +36 -0
- package/dist/public-types.d.ts +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { DesignResourceImplementationFeasibilityV1, DesignResourceTechnicalSourceRecordV1 } from "./design-resource-implementation-feasibility-types.js";
|
|
2
|
+
export declare function invalidFeasibility(code: string, detail: string): never;
|
|
3
|
+
export declare function unique(values: string[], code: string, detail?: string): void;
|
|
4
|
+
export declare function requireKnownRefs<T>(refs: string[], values: Map<string, T>, code: string, detail?: string): void;
|
|
5
|
+
export declare function requireSourceRole(refs: string[], sources: Map<string, DesignResourceTechnicalSourceRecordV1>, role: DesignResourceTechnicalSourceRecordV1["roles"][number], code: string, detail: string): void;
|
|
6
|
+
export declare function requireAtLeastOneSourceRole(refs: string[], sources: Map<string, DesignResourceTechnicalSourceRecordV1>, role: DesignResourceTechnicalSourceRecordV1["roles"][number], code: string, detail: string): void;
|
|
7
|
+
export declare function assertSameSet(actual: string[], expected: string[], code: string): void;
|
|
8
|
+
export declare function assertNoExactVisualValues(values: string[], detail: string): void;
|
|
9
|
+
export declare function validateNoExactVisualValueCarriers(document: DesignResourceImplementationFeasibilityV1): void;
|
|
10
|
+
export declare function cellPair(familyRef: string, profileRef: string): string;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
const EXACT_VISUAL_VALUE_PATTERNS = [
|
|
2
|
+
/#[0-9a-f]{3,8}\b/iu,
|
|
3
|
+
/\b(?:rgb|rgba|hsl|hsla|hwb|lab|lch|oklab|oklch)\s*\(/iu,
|
|
4
|
+
/\b\d+(?:\.\d+)?(?:px|rem|em|pt|pc|vh|vw|vmin|vmax|ch|ex|deg)\b/iu,
|
|
5
|
+
/\b(?:color|background|font(?:-family|-size|-weight)?|line-height|border-radius|radius|padding|margin|gap|width|height|opacity|duration|easing|shadow)\s*[:=]\s*\S+/iu,
|
|
6
|
+
/--[a-z0-9_-]+\s*:\s*\S+/iu,
|
|
7
|
+
];
|
|
8
|
+
const TIME_VALUE_PATTERN = /\b\d+(?:\.\d+)?(?:ms|s)\b/giu;
|
|
9
|
+
const MOTION_TIME_CONTEXT = /\b(?:animation|transition|motion|duration|delay|easing|timeline|keyframes?|fade|spring|stagger|enter|exit|hover|press|ease(?:-in|-out|-in-out)?)\b/iu;
|
|
10
|
+
const TECHNICAL_TIME_CONTEXT = /\b(?:build|compile|bundle|generation|ci|tests?|startup|initialization|latency|timeout|network|benchmark|runtime\s+cost|render\s+cost|benchmark\s+execution)\b/iu;
|
|
11
|
+
const TIME_CONTEXT_RADIUS = 80;
|
|
12
|
+
export function invalidFeasibility(code, detail) {
|
|
13
|
+
throw new Error(`design_resource_implementation_feasibility_invalid:${code}${detail ? `:${detail}` : ""}`);
|
|
14
|
+
}
|
|
15
|
+
export function unique(values, code, detail = "") {
|
|
16
|
+
if (new Set(values).size !== values.length)
|
|
17
|
+
invalidFeasibility(code, detail || values.join(","));
|
|
18
|
+
}
|
|
19
|
+
export function requireKnownRefs(refs, values, code, detail = "") {
|
|
20
|
+
for (const ref of refs)
|
|
21
|
+
if (!values.has(ref))
|
|
22
|
+
invalidFeasibility(code, detail ? `${detail}:${ref}` : ref);
|
|
23
|
+
}
|
|
24
|
+
export function requireSourceRole(refs, sources, role, code, detail) {
|
|
25
|
+
requireKnownRefs(refs, sources, code, detail);
|
|
26
|
+
for (const ref of refs)
|
|
27
|
+
if (!sources.get(ref).roles.includes(role))
|
|
28
|
+
invalidFeasibility(code, `${detail}:${ref}:${role}`);
|
|
29
|
+
}
|
|
30
|
+
export function requireAtLeastOneSourceRole(refs, sources, role, code, detail) {
|
|
31
|
+
if (!refs.some((ref) => sources.get(ref)?.roles.includes(role)))
|
|
32
|
+
invalidFeasibility(code, `${detail}:${role}`);
|
|
33
|
+
}
|
|
34
|
+
export function assertSameSet(actual, expected, code) {
|
|
35
|
+
const left = [...actual].sort(compareText);
|
|
36
|
+
const right = [...expected].sort(compareText);
|
|
37
|
+
if (left.length !== right.length ||
|
|
38
|
+
left.some((value, index) => value !== right[index]))
|
|
39
|
+
invalidFeasibility(code, `${left.join(",")}:${right.join(",")}`);
|
|
40
|
+
}
|
|
41
|
+
export function assertNoExactVisualValues(values, detail) {
|
|
42
|
+
for (const value of values)
|
|
43
|
+
if (EXACT_VISUAL_VALUE_PATTERNS.some((pattern) => pattern.test(value)) ||
|
|
44
|
+
hasForbiddenTimeValue(value))
|
|
45
|
+
invalidFeasibility("exact_visual_value_forbidden", detail);
|
|
46
|
+
}
|
|
47
|
+
function hasForbiddenTimeValue(value) {
|
|
48
|
+
for (const match of value.matchAll(TIME_VALUE_PATTERN)) {
|
|
49
|
+
const index = match.index;
|
|
50
|
+
const context = value.slice(Math.max(0, index - TIME_CONTEXT_RADIUS), Math.min(value.length, index + match[0].length + TIME_CONTEXT_RADIUS));
|
|
51
|
+
if (MOTION_TIME_CONTEXT.test(context))
|
|
52
|
+
return true;
|
|
53
|
+
if (!TECHNICAL_TIME_CONTEXT.test(context))
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
export function validateNoExactVisualValueCarriers(document) {
|
|
59
|
+
for (const observation of document.substrate_observations)
|
|
60
|
+
if (observation.reason !== null)
|
|
61
|
+
assertNoExactVisualValues([observation.reason], `substrate_observation:${observation.kind}:reason`);
|
|
62
|
+
for (const cell of document.component_family_cells)
|
|
63
|
+
for (const realization of cell.feasible_realizations) {
|
|
64
|
+
assertNoExactVisualValues(realization.observed_costs, `realization:${realization.key}:observed_costs`);
|
|
65
|
+
assertNoExactVisualValues(realization.observed_risks, `realization:${realization.key}:observed_risks`);
|
|
66
|
+
}
|
|
67
|
+
for (const blocker of document.blockers)
|
|
68
|
+
assertNoExactVisualValues([blocker.description], `blocker:${blocker.key}:description`);
|
|
69
|
+
}
|
|
70
|
+
export function cellPair(familyRef, profileRef) {
|
|
71
|
+
return `${familyRef}\0${profileRef}`;
|
|
72
|
+
}
|
|
73
|
+
function compareText(left, right) {
|
|
74
|
+
return left < right ? -1 : left > right ? 1 : 0;
|
|
75
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { DesignResourceTechnicalFeasibilityInputV1, LoadedDesignResourceImplementationFeasibilityV1 } from "./design-resource-implementation-feasibility-types.js";
|
|
2
|
+
import type { DesignResourceImplementationFeasibilityTargetModel } from "./design-resource-implementation-feasibility-model.js";
|
|
3
|
+
export declare function readAndValidateDesignResourceImplementationFeasibility(repository: string, handoffPath: string, inputs: DesignResourceTechnicalFeasibilityInputV1[], targetModels: Map<string, DesignResourceImplementationFeasibilityTargetModel>, canonicalResourcePaths: Set<string>): Promise<LoadedDesignResourceImplementationFeasibilityV1[]>;
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { readFile, stat } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { parseDesignResourceImplementationFeasibilityJson } from "./design-resource-implementation-feasibility-shape.js";
|
|
4
|
+
import { loadDesignResourceFeasibilityDecisionSource, } from "./design-resource-implementation-feasibility-source-decision.js";
|
|
5
|
+
import { validateFeasibilityDocument } from "./design-resource-implementation-feasibility-validation-document.js";
|
|
6
|
+
import { invalidFeasibility, unique, } from "./design-resource-implementation-feasibility-validation-support.js";
|
|
7
|
+
import { assertProtectedRepositoryFile } from "./long-task-protected-files.js";
|
|
8
|
+
import { sha256Hex } from "./strict-codec.js";
|
|
9
|
+
const FEASIBILITY_MAX_BYTES = 2_097_152;
|
|
10
|
+
const TECHNICAL_SOURCE_MAX_BYTES = 16_777_216;
|
|
11
|
+
export async function readAndValidateDesignResourceImplementationFeasibility(repository, handoffPath, inputs, targetModels, canonicalResourcePaths) {
|
|
12
|
+
unique(inputs.map((item) => item.key), "input_key_duplicate");
|
|
13
|
+
unique(inputs.map((item) => item.path), "input_path_duplicate");
|
|
14
|
+
unique(inputs.map((item) => item.target_ref), "input_target_duplicate");
|
|
15
|
+
for (const input of inputs)
|
|
16
|
+
if (!targetModels.has(input.target_ref))
|
|
17
|
+
invalidFeasibility("input_target_unknown", input.target_ref);
|
|
18
|
+
validateTargetInputCoverage(inputs, targetModels);
|
|
19
|
+
const loaded = [];
|
|
20
|
+
const sourcePathIdentities = new Map();
|
|
21
|
+
for (const input of inputs) {
|
|
22
|
+
const model = targetModels.get(input.target_ref);
|
|
23
|
+
if (!model)
|
|
24
|
+
invalidFeasibility("input_target_unknown", input.target_ref);
|
|
25
|
+
if (input.path === handoffPath)
|
|
26
|
+
invalidFeasibility("input_must_not_be_handoff", input.key);
|
|
27
|
+
if (canonicalResourcePaths.has(input.path))
|
|
28
|
+
invalidFeasibility("input_mixed_into_canonical_resources", input.path);
|
|
29
|
+
const file = await assertProtectedRepositoryFile(repository, path.resolve(repository, ...input.path.split("/")), `design_resource_feasibility:${input.key}`);
|
|
30
|
+
const size = (await stat(file)).size;
|
|
31
|
+
if (size > FEASIBILITY_MAX_BYTES)
|
|
32
|
+
invalidFeasibility("input_byte_limit_exceeded", `${input.key}:bytes=${size}:limit=${FEASIBILITY_MAX_BYTES}`);
|
|
33
|
+
const bytes = await readFile(file);
|
|
34
|
+
const digest = sha256Hex(bytes);
|
|
35
|
+
if (digest !== input.sha256)
|
|
36
|
+
invalidFeasibility("input_digest_mismatch", `${input.key}:${input.sha256}:${digest}`);
|
|
37
|
+
const content = bytes.toString("utf8");
|
|
38
|
+
if (!Buffer.from(content, "utf8").equals(bytes))
|
|
39
|
+
invalidFeasibility("input_utf8_invalid", input.key);
|
|
40
|
+
const document = parseDesignResourceImplementationFeasibilityJson(content);
|
|
41
|
+
if (document.key !== input.key)
|
|
42
|
+
invalidFeasibility("input_key_mismatch", `${input.key}:${document.key}`);
|
|
43
|
+
if (document.target_ref !== input.target_ref)
|
|
44
|
+
invalidFeasibility("input_target_mismatch", `${input.target_ref}:${document.target_ref}`);
|
|
45
|
+
const decisionSources = await validateTechnicalSourceRecords(repository, handoffPath, input.path, document.source_records, canonicalResourcePaths, sourcePathIdentities);
|
|
46
|
+
await validateFeasibilityDocument(repository, document, model, decisionSources);
|
|
47
|
+
loaded.push({
|
|
48
|
+
index: input,
|
|
49
|
+
document,
|
|
50
|
+
identity: {
|
|
51
|
+
key: input.key,
|
|
52
|
+
target_ref: input.target_ref,
|
|
53
|
+
path: input.path,
|
|
54
|
+
sha256: digest,
|
|
55
|
+
realization_mode: document.realization_mode,
|
|
56
|
+
component_family_cells: document.component_family_cells.length,
|
|
57
|
+
blockers: document.blockers.length,
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
return loaded;
|
|
62
|
+
}
|
|
63
|
+
function validateTargetInputCoverage(inputs, targetModels) {
|
|
64
|
+
if (!inputs.length)
|
|
65
|
+
return;
|
|
66
|
+
const indexedTargets = new Set(inputs.map((item) => item.target_ref));
|
|
67
|
+
for (const model of targetModels.values())
|
|
68
|
+
if (model.source_profile_kind !== "reference" &&
|
|
69
|
+
!indexedTargets.has(model.target_ref))
|
|
70
|
+
invalidFeasibility("implementation_target_input_missing", model.target_ref);
|
|
71
|
+
}
|
|
72
|
+
async function validateTechnicalSourceRecords(repository, handoffPath, inputPath, records, canonicalResourcePaths, sharedPathIdentities) {
|
|
73
|
+
const decisionSources = new Map();
|
|
74
|
+
unique(records.map((item) => item.key), "source_record_key_duplicate");
|
|
75
|
+
unique(records.map((item) => `${item.path}\0${item.locator.kind}\0${item.locator.value}`), "source_record_locator_duplicate");
|
|
76
|
+
for (const record of records) {
|
|
77
|
+
if (!record.roles.length)
|
|
78
|
+
invalidFeasibility("source_record_roles_required", record.key);
|
|
79
|
+
unique(record.roles, "source_record_role_duplicate", record.key);
|
|
80
|
+
if (record.path === handoffPath || record.path === inputPath)
|
|
81
|
+
invalidFeasibility("source_record_self_reference", `${record.key}:${record.path}`);
|
|
82
|
+
if (canonicalResourcePaths.has(record.path))
|
|
83
|
+
invalidFeasibility("technical_source_mixed_into_canonical_resources", record.path);
|
|
84
|
+
validateSharedSourceIdentity(record, sharedPathIdentities);
|
|
85
|
+
const file = await assertProtectedRepositoryFile(repository, path.resolve(repository, ...record.path.split("/")), `design_resource_feasibility_source:${record.key}`);
|
|
86
|
+
const size = (await stat(file)).size;
|
|
87
|
+
if (size > TECHNICAL_SOURCE_MAX_BYTES)
|
|
88
|
+
invalidFeasibility("source_record_byte_limit_exceeded", `${record.key}:bytes=${size}:limit=${TECHNICAL_SOURCE_MAX_BYTES}`);
|
|
89
|
+
const bytes = await readFile(file);
|
|
90
|
+
const digest = sha256Hex(bytes);
|
|
91
|
+
if (digest !== record.sha256)
|
|
92
|
+
invalidFeasibility("source_record_digest_mismatch", `${record.key}:${record.sha256}:${digest}`);
|
|
93
|
+
const decisionSource = validateSourceLocator(record, bytes);
|
|
94
|
+
if (decisionSource)
|
|
95
|
+
decisionSources.set(record.key, decisionSource);
|
|
96
|
+
}
|
|
97
|
+
return decisionSources;
|
|
98
|
+
}
|
|
99
|
+
function validateSharedSourceIdentity(record, sharedPathIdentities) {
|
|
100
|
+
const identity = `${record.media_type}\0${record.sha256}`;
|
|
101
|
+
const previous = sharedPathIdentities.get(record.path);
|
|
102
|
+
if (previous && previous !== identity)
|
|
103
|
+
invalidFeasibility("source_record_path_identity_conflict", record.path);
|
|
104
|
+
sharedPathIdentities.set(record.path, identity);
|
|
105
|
+
}
|
|
106
|
+
function validateSourceLocator(record, bytes) {
|
|
107
|
+
if (record.locator.kind === "whole_resource")
|
|
108
|
+
return null;
|
|
109
|
+
const content = bytes.toString("utf8");
|
|
110
|
+
if (!Buffer.from(content, "utf8").equals(bytes))
|
|
111
|
+
invalidFeasibility("source_record_utf8_invalid", record.key);
|
|
112
|
+
if (record.locator.kind === "source_item")
|
|
113
|
+
return loadDesignResourceFeasibilityDecisionSource(record, content);
|
|
114
|
+
if (record.locator.kind === "json_pointer") {
|
|
115
|
+
validateJsonPointer(record, content);
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
if (!content.includes(record.locator.value))
|
|
119
|
+
invalidFeasibility("source_record_locator_unresolved", `${record.key}:${record.locator.value}`);
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
function validateJsonPointer(record, content) {
|
|
123
|
+
let current;
|
|
124
|
+
try {
|
|
125
|
+
current = JSON.parse(content);
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
invalidFeasibility("source_record_json_invalid", record.key);
|
|
129
|
+
}
|
|
130
|
+
for (const raw of record.locator.value.slice(1).split("/")) {
|
|
131
|
+
const segment = raw.replace(/~1/gu, "/").replace(/~0/gu, "~");
|
|
132
|
+
if (!current ||
|
|
133
|
+
typeof current !== "object" ||
|
|
134
|
+
!Object.hasOwn(current, segment))
|
|
135
|
+
invalidFeasibility("source_record_locator_unresolved", `${record.key}:${record.locator.value}`);
|
|
136
|
+
current = current[segment];
|
|
137
|
+
}
|
|
138
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { parseDesignResourceHandoffResources } from "./design-resource-handoff-shape-structure.js";
|
|
2
2
|
import { contractKey, sourceItemKeys, stableKey, stableKeys, } from "./design-resource-handoff-shape-primitives.js";
|
|
3
|
+
import { parseDesignResourceTechnicalFeasibilityInputs } from "./design-resource-implementation-feasibility-shape.js";
|
|
3
4
|
import { array, literal, object, repositoryFile, string, strings, } from "./long-task-shape-primitives.js";
|
|
4
5
|
export { parseDesignResourceObservableRuleManifestJson, parseDesignResourceObservableRuleManifestShape, } from "./design-resource-symbolic-manifest-shape.js";
|
|
5
6
|
export function parseDesignResourceSymbolicHandoffShape(value) {
|
|
@@ -14,13 +15,14 @@ export function parseDesignResourceSymbolicHandoffShape(value) {
|
|
|
14
15
|
"targets",
|
|
15
16
|
"coverage",
|
|
16
17
|
"proposal",
|
|
17
|
-
]);
|
|
18
|
+
], ["technical_feasibility_inputs"]);
|
|
18
19
|
return {
|
|
19
20
|
schema_version: literal(root.schema_version, ["design-resource-handoff-v2"], `${label}.schema_version`),
|
|
20
21
|
representation: literal(root.representation, ["symbolic_rules_v2"], `${label}.representation`),
|
|
21
22
|
intent: literal(root.intent, ["implementation_handoff"], `${label}.intent`),
|
|
22
23
|
scope: parseScope(root.scope, label),
|
|
23
24
|
provenance: parseProvenance(root.provenance, label),
|
|
25
|
+
technical_feasibility_inputs: parseDesignResourceTechnicalFeasibilityInputs(root.technical_feasibility_inputs ?? [], `${label}.technical_feasibility_inputs`),
|
|
24
26
|
resources: parseDesignResourceHandoffResources(root.resources),
|
|
25
27
|
targets: parseTargets(root.targets, label),
|
|
26
28
|
coverage: parseCoverage(root.coverage, label),
|
|
@@ -3,6 +3,7 @@ import type { DesignResourceEnvironmentV1, DesignResourceFactLineageV1, DesignRe
|
|
|
3
3
|
import type { DesignResourceHandoffBlockerV1, DesignResourceHandoffResourceV1, DesignResourceHandoffSubjectV1, DesignResourceSourceProfileKind, DesignResourceVerificationMethod } from "./design-resource-handoff-types.js";
|
|
4
4
|
import type { CompiledSymbolicDenotationV1, SymbolicDenotationAxisDomain, SymbolicDenotationDisposition, SymbolicDenotationPredicate, SymbolicExtensionalPointV1 } from "./symbolic-denotation-types.js";
|
|
5
5
|
import type { DesignResourceSymbolicNoninterferenceCertificateV2 } from "./design-resource-symbolic-noninterference-types.js";
|
|
6
|
+
import type { DesignResourceImplementationFeasibilityIdentityV1, DesignResourceImplementationFeasibilityV1, DesignResourceTechnicalFeasibilityInputV1 } from "./design-resource-implementation-feasibility-types.js";
|
|
6
7
|
export type { DesignResourceSymbolicNoninterferenceArtifactV2, DesignResourceSymbolicNoninterferenceCertificateV2, DesignResourceSymbolicNoninterferenceDerivedResultV2, DesignResourceSymbolicNoninterferenceEquivalenceCaseV2, DesignResourceSymbolicNoninterferenceFailureWitnessV1, DesignResourceSymbolicNoninterferenceInputBindingV2, DesignResourceSymbolicNoninterferenceProofMethodV2, DesignResourceSymbolicNoninterferenceProofV2, DesignResourceSymbolicStaticDependencyNodeV2, DesignResourceSymbolicStaticDependencyRootV2, } from "./design-resource-symbolic-noninterference-types.js";
|
|
7
8
|
export interface DesignResourceSymbolicPopulationV2 {
|
|
8
9
|
key: string;
|
|
@@ -175,6 +176,7 @@ export interface DesignResourceHandoffV2 {
|
|
|
175
176
|
model: string;
|
|
176
177
|
design_system_id: string;
|
|
177
178
|
};
|
|
179
|
+
technical_feasibility_inputs: DesignResourceTechnicalFeasibilityInputV1[];
|
|
178
180
|
resources: DesignResourceHandoffResourceV1[];
|
|
179
181
|
targets: DesignResourceSymbolicHandoffTargetV2[];
|
|
180
182
|
coverage: DesignResourceSymbolicHandoffCoverageV2[];
|
|
@@ -199,6 +201,9 @@ export interface DesignResourceHandoffPreflightV2 extends ParsedDesignResourceHa
|
|
|
199
201
|
status: "ready";
|
|
200
202
|
manifest: DesignResourceObservableRuleManifestV2;
|
|
201
203
|
resource_hashes: Record<string, string>;
|
|
204
|
+
technical_feasibility_documents: DesignResourceImplementationFeasibilityV1[];
|
|
205
|
+
technical_feasibility_identities: DesignResourceImplementationFeasibilityIdentityV1[];
|
|
206
|
+
limitations: string[];
|
|
202
207
|
rule_projections: DesignResourceSymbolicRuleProjectionV2[];
|
|
203
208
|
metrics: {
|
|
204
209
|
semantic_obligations: number;
|
|
@@ -7,6 +7,8 @@ import { validateSymbolicCoverage } from "./design-resource-symbolic-region-vali
|
|
|
7
7
|
import { assertSameSet, invalid, requireExactRefs, unique, } from "./design-resource-symbolic-validation-support.js";
|
|
8
8
|
import { assertProtectedRepositoryFile } from "./long-task-protected-files.js";
|
|
9
9
|
import { sha256Hex } from "./strict-codec.js";
|
|
10
|
+
import { createV2ImplementationFeasibilityTargetModel } from "./design-resource-implementation-feasibility-model.js";
|
|
11
|
+
import { readAndValidateDesignResourceImplementationFeasibility } from "./design-resource-implementation-feasibility-validation.js";
|
|
10
12
|
export { designResourceSymbolicCertificateKey, designResourceSymbolicCombinedRuleDigest, designResourceSymbolicDependencyEdge, designResourceSymbolicNoninterferenceProofDigest, designResourceSymbolicObligationKey, designResourceSymbolicRuleKey, } from "./design-resource-symbolic-validation-support.js";
|
|
11
13
|
const V2_MANIFEST_MAX_BYTES = 8_388_608;
|
|
12
14
|
export async function preflightParsedDesignResourceSymbolicHandoff(repository, parsed) {
|
|
@@ -37,12 +39,23 @@ export async function preflightParsedDesignResourceSymbolicHandoff(repository, p
|
|
|
37
39
|
invalid("v2_manifest_identity_mismatch", `${manifest.scope_key}:${manifest.target_key}`);
|
|
38
40
|
const validated = validateDesignResourceSymbolicManifest(manifest, parsed, resources, contents);
|
|
39
41
|
validateSymbolicCoverage(parsed, manifest);
|
|
42
|
+
const feasibility = await readAndValidateDesignResourceImplementationFeasibility(repository, parsed.handoff_path, handoff.technical_feasibility_inputs, new Map([
|
|
43
|
+
[
|
|
44
|
+
target.key,
|
|
45
|
+
createV2ImplementationFeasibilityTargetModel(target, manifest),
|
|
46
|
+
],
|
|
47
|
+
]), new Set(handoff.resources.map((resource) => resource.path)));
|
|
40
48
|
return {
|
|
41
49
|
...parsed,
|
|
42
50
|
preflight_schema_version: "design-resource-handoff-preflight-v2",
|
|
43
51
|
status: "ready",
|
|
44
52
|
manifest,
|
|
45
53
|
resource_hashes: resourceHashes,
|
|
54
|
+
technical_feasibility_documents: feasibility.map((item) => item.document),
|
|
55
|
+
technical_feasibility_identities: feasibility.map((item) => item.identity),
|
|
56
|
+
limitations: target.source_profile.kind !== "reference" && !feasibility.length
|
|
57
|
+
? ["technical feasibility not declared"]
|
|
58
|
+
: [],
|
|
46
59
|
rule_projections: validated.ruleProjections,
|
|
47
60
|
metrics: validated.metrics,
|
|
48
61
|
};
|
|
@@ -19,11 +19,14 @@ import { captureWorkspaceManifest, repoRelative, } from "./long-task-workspace.j
|
|
|
19
19
|
export async function validateContractForActivation(options) {
|
|
20
20
|
const { contract, repository, workdir, mode } = options;
|
|
21
21
|
const diagnostics = options.diagnostics ?? [];
|
|
22
|
+
const structureOptions = {
|
|
23
|
+
allowDeferredDesignComponentBindingClosure: true,
|
|
24
|
+
};
|
|
22
25
|
if (mode === "collect")
|
|
23
|
-
for (const error of deliveryContractStructureDiagnostics(contract))
|
|
26
|
+
for (const error of deliveryContractStructureDiagnostics(contract, structureOptions))
|
|
24
27
|
addDiagnosticError(diagnostics, error);
|
|
25
28
|
else
|
|
26
|
-
validateDeliveryContractStructure(contract);
|
|
29
|
+
validateDeliveryContractStructure(contract, structureOptions);
|
|
27
30
|
const claims = await attempt(mode, diagnostics, () => compileProductClaimCoverage(contract));
|
|
28
31
|
if (mode === "fail_fast") {
|
|
29
32
|
const decisions = contract.source_claims
|
|
@@ -45,7 +48,7 @@ export async function validateContractForActivation(options) {
|
|
|
45
48
|
: undefined);
|
|
46
49
|
return items;
|
|
47
50
|
});
|
|
48
|
-
await attempt(mode, diagnostics, () => validateLongTaskDesignResourceHandoffs(contract, repository));
|
|
51
|
+
await attempt(mode, diagnostics, () => validateLongTaskDesignResourceHandoffs(contract, repository, sourceItems ?? []));
|
|
49
52
|
const risk = await attempt(mode, diagnostics, () => {
|
|
50
53
|
const decision = classifyLongTaskRisk(contract);
|
|
51
54
|
validateRiskProof(contract, decision);
|
|
@@ -83,11 +86,15 @@ export async function validateContractForActivation(options) {
|
|
|
83
86
|
const outcomes = [];
|
|
84
87
|
for (const outcome of contract.outcomes) {
|
|
85
88
|
const checks = [];
|
|
89
|
+
const blockedDesignAssertionRefsByCheck = new Map();
|
|
86
90
|
for (const check of outcome.acceptance.checks) {
|
|
87
91
|
const executionTarget = contract.task.execution_targets.find((target) => target.key === check.execution_target.target_ref);
|
|
88
92
|
if (!executionTarget)
|
|
89
93
|
continue;
|
|
90
|
-
const
|
|
94
|
+
const blockedDesignAssertionRefs = externallyBlockedDesignAssertionRefs(outcome, check, contract.global.acceptance.external_confirmations);
|
|
95
|
+
blockedDesignAssertionRefsByCheck.set(check.key, blockedDesignAssertionRefs);
|
|
96
|
+
const machineCheck = projectMachineCheck(check, blockedDesignAssertionRefs);
|
|
97
|
+
const frozen = await attempt(mode, diagnostics, () => freezeDeliveryCheck(machineCheck, outcome.key, repository, workspace, executionTarget, contract.task.execution_targets, designTargetsForCheck(outcome, check.key, contract.global.acceptance.external_confirmations), semanticFactClosure?.expectations_by_check.get(check.key) ?? [], scopeDeliveryBindings(outcome.key, outcome.technical.bindings), outcome.product.owner.path_globs, sourceBackedExecutionTargets.get(executionTarget.key) ?? null, observationAuthorityPaths), outcome.key, check.key);
|
|
91
98
|
if (frozen)
|
|
92
99
|
checks.push(frozen);
|
|
93
100
|
}
|
|
@@ -96,7 +103,12 @@ export async function validateContractForActivation(options) {
|
|
|
96
103
|
internal_id: `OUT.${outcome.key}`,
|
|
97
104
|
generated_claims: claims?.by_outcome[outcome.key] ?? [],
|
|
98
105
|
risk_reasons: risk?.reasons_by_outcome[outcome.key] ?? [],
|
|
99
|
-
acceptance: {
|
|
106
|
+
acceptance: {
|
|
107
|
+
...outcome.acceptance,
|
|
108
|
+
checks,
|
|
109
|
+
counterfactual_controls: outcome.acceptance.counterfactual_controls.map((control) => projectCounterfactualControl(control, outcome.acceptance.checks.find((check) => check.key === control.check_key), blockedDesignAssertionRefsByCheck.get(control.check_key) ??
|
|
110
|
+
new Set())),
|
|
111
|
+
},
|
|
100
112
|
});
|
|
101
113
|
}
|
|
102
114
|
const allChecks = [
|
|
@@ -130,9 +142,11 @@ export async function validateContractForActivation(options) {
|
|
|
130
142
|
outcomes,
|
|
131
143
|
};
|
|
132
144
|
}
|
|
133
|
-
function designTargetsForCheck(outcome, checkKey) {
|
|
145
|
+
function designTargetsForCheck(outcome, checkKey, confirmations) {
|
|
134
146
|
return (outcome.product.surface_bindings ?? []).flatMap((binding) => binding.design_targets
|
|
135
|
-
.filter((target) => target.conformance_check_ref === checkKey
|
|
147
|
+
.filter((target) => target.conformance_check_ref === checkKey &&
|
|
148
|
+
!confirmations.some((confirmation) => confirmation.blocks_target &&
|
|
149
|
+
confirmation.impact_claims.some((claimRef) => target.claim_refs.some((targetClaimRef) => claimRef === `${outcome.key}.${targetClaimRef}`))))
|
|
136
150
|
.map((target) => ({
|
|
137
151
|
...target,
|
|
138
152
|
surface_binding_ref: binding.key,
|
|
@@ -140,6 +154,62 @@ function designTargetsForCheck(outcome, checkKey) {
|
|
|
140
154
|
target_ref: binding.target_ref,
|
|
141
155
|
})));
|
|
142
156
|
}
|
|
157
|
+
function externallyBlockedDesignAssertionRefs(outcome, check, confirmations) {
|
|
158
|
+
const refs = new Set();
|
|
159
|
+
const impactedClaims = new Set();
|
|
160
|
+
for (const binding of outcome.product.surface_bindings ?? [])
|
|
161
|
+
for (const target of binding.design_targets) {
|
|
162
|
+
if (target.conformance_check_ref !== check.key)
|
|
163
|
+
continue;
|
|
164
|
+
const blocked = confirmations.some((confirmation) => confirmation.blocks_target &&
|
|
165
|
+
confirmation.impact_claims.some((claimRef) => target.claim_refs.some((targetClaimRef) => claimRef === `${outcome.key}.${targetClaimRef}`)));
|
|
166
|
+
if (!blocked)
|
|
167
|
+
continue;
|
|
168
|
+
for (const confirmation of confirmations)
|
|
169
|
+
if (confirmation.blocks_target &&
|
|
170
|
+
confirmation.impact_claims.some((claimRef) => target.claim_refs.some((targetClaimRef) => claimRef === `${outcome.key}.${targetClaimRef}`)))
|
|
171
|
+
for (const claimRef of confirmation.impact_claims)
|
|
172
|
+
impactedClaims.add(claimRef);
|
|
173
|
+
refs.add(target.conformance_assertion_ref);
|
|
174
|
+
for (const method of target.verification_method_bindings)
|
|
175
|
+
refs.add(method.assertion_ref);
|
|
176
|
+
for (const method of target.symbolic_method_bindings ?? [])
|
|
177
|
+
refs.add(method.assertion_ref);
|
|
178
|
+
if (target.symbolic_certificate_binding)
|
|
179
|
+
refs.add(target.symbolic_certificate_binding.assertion_ref);
|
|
180
|
+
}
|
|
181
|
+
for (const assertion of [
|
|
182
|
+
...check.positive_assertions,
|
|
183
|
+
...check.negative_assertions,
|
|
184
|
+
])
|
|
185
|
+
if (assertion.evidence_capabilities.includes("state_delta") &&
|
|
186
|
+
assertion.claims.length > 0 &&
|
|
187
|
+
assertion.claims.every((claimRef) => impactedClaims.has(`${outcome.key}.${claimRef}`)))
|
|
188
|
+
refs.add(assertion.key);
|
|
189
|
+
return refs;
|
|
190
|
+
}
|
|
191
|
+
function projectMachineCheck(check, externallyBlockedAssertionRefs) {
|
|
192
|
+
if (!externallyBlockedAssertionRefs.size)
|
|
193
|
+
return check;
|
|
194
|
+
return {
|
|
195
|
+
...check,
|
|
196
|
+
positive_assertions: check.positive_assertions.filter((assertion) => !externallyBlockedAssertionRefs.has(assertion.key)),
|
|
197
|
+
negative_assertions: check.negative_assertions.filter((assertion) => !externallyBlockedAssertionRefs.has(assertion.key)),
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
function projectCounterfactualControl(control, check, externallyBlockedAssertionRefs) {
|
|
201
|
+
if (!check || !externallyBlockedAssertionRefs.size)
|
|
202
|
+
return control;
|
|
203
|
+
const externallyBlockedClaims = new Set([...check.positive_assertions, ...check.negative_assertions]
|
|
204
|
+
.filter((assertion) => externallyBlockedAssertionRefs.has(assertion.key))
|
|
205
|
+
.flatMap((assertion) => assertion.claims));
|
|
206
|
+
return {
|
|
207
|
+
...control,
|
|
208
|
+
claims: control.claims.filter((claimRef) => !externallyBlockedClaims.has(claimRef)),
|
|
209
|
+
expected_assertion_failures: control.expected_assertion_failures.filter((assertionRef) => !externallyBlockedAssertionRefs.has(assertionRef)),
|
|
210
|
+
preserved_assertions: control.preserved_assertions.filter((assertionRef) => !externallyBlockedAssertionRefs.has(assertionRef)),
|
|
211
|
+
};
|
|
212
|
+
}
|
|
143
213
|
async function attempt(mode, diagnostics, action, outcomeKey, checkKey) {
|
|
144
214
|
try {
|
|
145
215
|
return await action();
|