project-tiny-context-harness 0.8.13 → 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 +53 -28
- package/assets/README.md +52 -25
- package/assets/README.zh-CN.md +55 -26
- package/assets/agents/AGENTS_CORE.md +2 -2
- package/assets/agents/long-task-implementation.toml +1 -1
- 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/assets/skills/long-task-workflow/SKILL.md +9 -7
- package/assets/skills/long-task-workflow/agents/openai.yaml +1 -1
- package/assets/skills/long-task-workflow/references/authority-lifecycle.md +1 -1
- package/dist/commands/design-resource.js +9 -2
- package/dist/commands/long-task-revision.js +4 -4
- 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-authority-revision-brief.js +3 -1
- package/dist/lib/long-task-authority-revision-summary.js +6 -2
- package/dist/lib/long-task-authority-revision-types.d.ts +2 -0
- 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 +16 -4
- package/dist/lib/long-task-freshness.js +1 -1
- package/dist/lib/long-task-git.d.ts +26 -0
- package/dist/lib/long-task-git.js +130 -0
- package/dist/lib/long-task-paths.js +1 -1
- package/dist/lib/long-task-process-runtime-closure.js +74 -42
- 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/long-task-verifier-authority.js +2 -0
- package/dist/lib/long-task-workspace-manifest.d.ts +8 -0
- package/dist/lib/long-task-workspace-manifest.js +173 -0
- package/dist/lib/long-task-workspace-snapshot.d.ts +8 -0
- package/dist/lib/long-task-workspace-snapshot.js +176 -0
- package/dist/lib/long-task-workspace.d.ts +4 -25
- package/dist/lib/long-task-workspace.js +3 -432
- package/dist/lib/repository-path-safety.d.ts +2 -0
- package/dist/lib/repository-path-safety.js +36 -0
- package/dist/long-task-hook.js +12 -3
- package/dist/public-types.d.ts +1 -0
- package/package.json +1 -1
|
@@ -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();
|
|
@@ -15,7 +15,9 @@ export function buildAuthorityRevisionDecisionBrief(summary, changeClass, approv
|
|
|
15
15
|
addCategory(summary.source_or_claims_changed, "Source/Claims", detail("Source or Claim authority changed", summary.source_claim_changes));
|
|
16
16
|
addCategory(summary.context_authority_changed, "Context authority", "Controlling Context authority changed.");
|
|
17
17
|
addCategory(summary.acceptance_or_proof_weakened, "acceptance/proof", detail("Acceptance or proof was reduced", summary.proof_reductions));
|
|
18
|
-
addCategory(summary.verifier_or_runner_changed, "verifier/runner",
|
|
18
|
+
addCategory(summary.verifier_or_runner_changed, "verifier/runner", summary.verifier_content_changed
|
|
19
|
+
? detail("Verifier content changed; prior evidence is invalid and semantic preservation is not independently established", summary.verifier_files_changed)
|
|
20
|
+
: "Verifier or runner authority changed.");
|
|
19
21
|
addCategory(summary.write_scope_expanded, "write scope", detail("Owner or allowed write scope expanded", uniqueSorted([
|
|
20
22
|
...summary.expanded_owner_paths,
|
|
21
23
|
...summary.expanded_expected_change_paths,
|
|
@@ -59,7 +59,6 @@ const PROOF_REDUCTION_REASONS = new Set([
|
|
|
59
59
|
"rollback_or_recovery_weakened",
|
|
60
60
|
"counterfactual_removed",
|
|
61
61
|
"population_weakened",
|
|
62
|
-
"verifier_content_changed",
|
|
63
62
|
"acceptance_not_monotonic",
|
|
64
63
|
]);
|
|
65
64
|
export function classifyAuthorityRevision(diff) {
|
|
@@ -136,6 +135,8 @@ export function summarizeAuthorityRevision(diff, outcomeKeys) {
|
|
|
136
135
|
verifier_or_runner_changed: diff.verifier_content_changed ||
|
|
137
136
|
diff.verifier_runtime_locator_changed ||
|
|
138
137
|
diff.runner_definitions_changed.length > 0,
|
|
138
|
+
verifier_content_changed: diff.verifier_content_changed,
|
|
139
|
+
verifier_files_changed: uniqueSorted(diff.verifier_files_changed),
|
|
139
140
|
write_scope_expanded: diff.owner_or_path_boundary_changed,
|
|
140
141
|
risk_changed: diff.risk_changed,
|
|
141
142
|
external_confirmations_changed: diff.external_confirmations_changed,
|
|
@@ -184,13 +185,16 @@ export function projectAuthorityRevisionDecision(value) {
|
|
|
184
185
|
? {
|
|
185
186
|
...computedSummary,
|
|
186
187
|
...storedSummary,
|
|
188
|
+
acceptance_or_proof_weakened: computedSummary.acceptance_or_proof_weakened,
|
|
189
|
+
verifier_content_changed: computedSummary.verifier_content_changed,
|
|
190
|
+
verifier_files_changed: computedSummary.verifier_files_changed,
|
|
187
191
|
semantic_fields_changed: storedSummary.semantic_fields_changed ??
|
|
188
192
|
computedSummary.semantic_fields_changed,
|
|
189
193
|
source_claim_changes: storedSummary.source_claim_changes ??
|
|
190
194
|
computedSummary.source_claim_changes,
|
|
191
195
|
product_claim_changes: storedSummary.product_claim_changes ??
|
|
192
196
|
computedSummary.product_claim_changes,
|
|
193
|
-
proof_reductions:
|
|
197
|
+
proof_reductions: computedSummary.proof_reductions,
|
|
194
198
|
external_confirmation_changes: storedSummary.external_confirmation_changes ??
|
|
195
199
|
computedSummary.external_confirmation_changes,
|
|
196
200
|
user_decision_reasons: storedSummary.user_decision_reasons ??
|
|
@@ -7,6 +7,8 @@ export interface AuthorityRevisionApprovalSummaryV2 {
|
|
|
7
7
|
context_authority_changed: boolean;
|
|
8
8
|
acceptance_or_proof_weakened: boolean;
|
|
9
9
|
verifier_or_runner_changed: boolean;
|
|
10
|
+
verifier_content_changed: boolean;
|
|
11
|
+
verifier_files_changed: string[];
|
|
10
12
|
write_scope_expanded: boolean;
|
|
11
13
|
risk_changed: boolean;
|
|
12
14
|
external_confirmations_changed: boolean;
|