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,125 @@
|
|
|
1
|
+
import { validateDesignFactRefs } from "./design-resource-implementation-feasibility-validation-facts.js";
|
|
2
|
+
import { validateFeasibleRealization, validateRequiredRealization, } from "./design-resource-implementation-feasibility-validation-realizations.js";
|
|
3
|
+
import { assertSameSet, cellPair, invalidFeasibility, requireKnownRefs, unique, } from "./design-resource-implementation-feasibility-validation-support.js";
|
|
4
|
+
import { DESIGN_RESOURCE_FEASIBILITY_DECISION_SCHEMA, deriveDesignResourceFeasibilityConditionScopeSha256, requireExactFeasibilityDecisionProjection, } from "./design-resource-implementation-feasibility-source-decision.js";
|
|
5
|
+
export async function validateFeasibilityCells(repository, document, model, profileRefs, sources, decisionSources) {
|
|
6
|
+
unique(document.component_family_cells.map((item) => item.key), "cell_key_duplicate");
|
|
7
|
+
unique(document.blockers.map((item) => item.key), "blocker_key_duplicate");
|
|
8
|
+
const families = new Set(model.component_family_refs);
|
|
9
|
+
const blockers = new Map(document.blockers.map((item) => [item.key, item]));
|
|
10
|
+
const componentOwnerObservation = document.substrate_observations.find((observation) => observation.kind === "component_owner_roots");
|
|
11
|
+
const componentOwnerRoots = componentOwnerObservation?.value?.kind === "repository_paths"
|
|
12
|
+
? componentOwnerObservation.value.paths
|
|
13
|
+
: [];
|
|
14
|
+
const usedBlockers = new Set();
|
|
15
|
+
const cellPairs = [];
|
|
16
|
+
const realizationKeys = [];
|
|
17
|
+
for (const cell of document.component_family_cells) {
|
|
18
|
+
cellPairs.push(cellPair(cell.component_family_ref, cell.condition_profile_ref));
|
|
19
|
+
await validateCell(repository, cell, document, model, families, profileRefs, sources, decisionSources, componentOwnerRoots, blockers, usedBlockers, realizationKeys);
|
|
20
|
+
}
|
|
21
|
+
unique(cellPairs, "component_family_condition_cell_duplicate");
|
|
22
|
+
unique(realizationKeys, "realization_key_duplicate");
|
|
23
|
+
if (document.realization_mode !== "reference") {
|
|
24
|
+
const expected = model.component_family_refs.flatMap((familyRef) => [...profileRefs].map((profileRef) => cellPair(familyRef, profileRef)));
|
|
25
|
+
assertSameSet(cellPairs, expected, "component_family_condition_cell_set_mismatch");
|
|
26
|
+
}
|
|
27
|
+
validateBlockers(document, model, families, profileRefs, sources, decisionSources, usedBlockers);
|
|
28
|
+
validateSubstrateObservationBlockerCoverage(document, model);
|
|
29
|
+
}
|
|
30
|
+
export function validateSubstrateObservationBlockerCoverage(document, model) {
|
|
31
|
+
const observations = new Map(document.substrate_observations.map((observation) => [
|
|
32
|
+
observation.kind,
|
|
33
|
+
observation,
|
|
34
|
+
]));
|
|
35
|
+
const blockers = new Map(document.blockers.map((blocker) => [blocker.key, blocker]));
|
|
36
|
+
for (const blocker of document.blockers) {
|
|
37
|
+
unique(blocker.substrate_observation_refs, "blocker_substrate_observation_ref_duplicate", blocker.key);
|
|
38
|
+
for (const observationRef of blocker.substrate_observation_refs) {
|
|
39
|
+
const observation = observations.get(observationRef);
|
|
40
|
+
if (!observation ||
|
|
41
|
+
!["decision_required", "unavailable"].includes(observation.disposition))
|
|
42
|
+
invalidFeasibility("blocker_substrate_observation_not_unresolved", `${blocker.key}:${observationRef}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const unresolved = document.substrate_observations.filter((observation) => ["decision_required", "unavailable"].includes(observation.disposition));
|
|
46
|
+
if (unresolved.length && model.component_family_refs.length === 0)
|
|
47
|
+
invalidFeasibility("unresolved_substrate_without_family_carrier", unresolved.map((observation) => observation.kind).join(","));
|
|
48
|
+
for (const cell of document.component_family_cells)
|
|
49
|
+
for (const observation of unresolved)
|
|
50
|
+
if (!cell.blocker_refs.some((blockerRef) => blockers
|
|
51
|
+
.get(blockerRef)
|
|
52
|
+
?.substrate_observation_refs.includes(observation.kind)))
|
|
53
|
+
invalidFeasibility("unresolved_substrate_observation_cell_uncovered", `${observation.kind}:${cell.key}`);
|
|
54
|
+
}
|
|
55
|
+
async function validateCell(repository, cell, document, model, families, profileRefs, sources, decisionSources, componentOwnerRoots, blockers, usedBlockers, realizationKeys) {
|
|
56
|
+
validateCellIdentity(cell, document.target_ref, families, profileRefs);
|
|
57
|
+
unique(cell.design_fact_refs, "cell_design_fact_ref_duplicate", cell.key);
|
|
58
|
+
if (!cell.design_fact_refs.length &&
|
|
59
|
+
document.realization_mode !== "reference")
|
|
60
|
+
invalidFeasibility("cell_design_fact_refs_required", cell.key);
|
|
61
|
+
validateDesignFactRefs(cell, model, document);
|
|
62
|
+
const conditionScopeSha256 = deriveDesignResourceFeasibilityConditionScopeSha256(document, model, cell.condition_profile_ref);
|
|
63
|
+
validateCellBlockers(cell, blockers, usedBlockers);
|
|
64
|
+
if (!cell.feasible_realizations.length && !cell.blocker_refs.length)
|
|
65
|
+
invalidFeasibility("cell_candidate_or_blocker_required", cell.key);
|
|
66
|
+
unique(cell.feasible_realizations.map((item) => item.key), "cell_realization_key_duplicate", cell.key);
|
|
67
|
+
for (const realization of cell.feasible_realizations) {
|
|
68
|
+
realizationKeys.push(realization.key);
|
|
69
|
+
await validateFeasibleRealization(repository, realization, sources, decisionSources, componentOwnerRoots, {
|
|
70
|
+
target_ref: cell.target_ref,
|
|
71
|
+
component_family_ref: cell.component_family_ref,
|
|
72
|
+
condition_scope_sha256: conditionScopeSha256,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
validateRequiredRealization(cell, sources, decisionSources, conditionScopeSha256);
|
|
76
|
+
}
|
|
77
|
+
function validateCellBlockers(cell, blockers, usedBlockers) {
|
|
78
|
+
unique(cell.blocker_refs, "cell_blocker_ref_duplicate", cell.key);
|
|
79
|
+
for (const blockerRef of cell.blocker_refs) {
|
|
80
|
+
const blocker = blockers.get(blockerRef);
|
|
81
|
+
if (!blocker)
|
|
82
|
+
invalidFeasibility("cell_blocker_unknown", `${cell.key}:${blockerRef}`);
|
|
83
|
+
if (blocker.target_ref !== cell.target_ref ||
|
|
84
|
+
blocker.component_family_ref !== cell.component_family_ref ||
|
|
85
|
+
blocker.condition_profile_ref !== cell.condition_profile_ref)
|
|
86
|
+
invalidFeasibility("cell_blocker_scope_mismatch", `${cell.key}:${blockerRef}`);
|
|
87
|
+
usedBlockers.add(blockerRef);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
function validateBlockers(document, model, families, profileRefs, sources, decisionSources, usedBlockers) {
|
|
91
|
+
for (const blocker of document.blockers) {
|
|
92
|
+
if (blocker.target_ref !== document.target_ref)
|
|
93
|
+
invalidFeasibility("blocker_target_mismatch", blocker.key);
|
|
94
|
+
if (!families.has(blocker.component_family_ref))
|
|
95
|
+
invalidFeasibility("blocker_component_family_unknown", blocker.key);
|
|
96
|
+
if (!profileRefs.has(blocker.condition_profile_ref))
|
|
97
|
+
invalidFeasibility("blocker_condition_profile_unknown", blocker.key);
|
|
98
|
+
if (!blocker.source_record_refs.length)
|
|
99
|
+
invalidFeasibility("blocker_source_required", blocker.key);
|
|
100
|
+
unique(blocker.source_record_refs, "blocker_source_duplicate", blocker.key);
|
|
101
|
+
requireKnownRefs(blocker.source_record_refs, sources, "blocker_source_unknown", blocker.key);
|
|
102
|
+
requireExactFeasibilityDecisionProjection(blocker.source_record_refs, decisionSources, {
|
|
103
|
+
schema_version: DESIGN_RESOURCE_FEASIBILITY_DECISION_SCHEMA,
|
|
104
|
+
mode: "feasibility_blocker",
|
|
105
|
+
target_ref: blocker.target_ref,
|
|
106
|
+
component_family_ref: blocker.component_family_ref,
|
|
107
|
+
condition_scope_sha256: deriveDesignResourceFeasibilityConditionScopeSha256(document, model, blocker.condition_profile_ref),
|
|
108
|
+
blocker_ref: blocker.key,
|
|
109
|
+
substrate_observation_refs: blocker.substrate_observation_refs,
|
|
110
|
+
}, `blocker:${blocker.key}`, {
|
|
111
|
+
allReferencesMustBeSourceItems: false,
|
|
112
|
+
allowedItemKinds: ["decision", "external_confirmation"],
|
|
113
|
+
});
|
|
114
|
+
if (!usedBlockers.has(blocker.key))
|
|
115
|
+
invalidFeasibility("blocker_unreferenced", blocker.key);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
function validateCellIdentity(cell, targetRef, families, profiles) {
|
|
119
|
+
if (cell.target_ref !== targetRef)
|
|
120
|
+
invalidFeasibility("cell_target_mismatch", cell.key);
|
|
121
|
+
if (!families.has(cell.component_family_ref))
|
|
122
|
+
invalidFeasibility("cell_component_family_unknown", cell.key);
|
|
123
|
+
if (!profiles.has(cell.condition_profile_ref))
|
|
124
|
+
invalidFeasibility("cell_condition_profile_unknown", cell.key);
|
|
125
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type DesignResourceImplementationFeasibilityV1 } from "./design-resource-implementation-feasibility-types.js";
|
|
2
|
+
import type { DesignResourceImplementationFeasibilityTargetModel } from "./design-resource-implementation-feasibility-model.js";
|
|
3
|
+
import type { DesignResourceFeasibilityDecisionSourceIndex } from "./design-resource-implementation-feasibility-source-decision.js";
|
|
4
|
+
export declare function validateFeasibilityDocument(repository: string, document: DesignResourceImplementationFeasibilityV1, model: DesignResourceImplementationFeasibilityTargetModel, decisionSources: DesignResourceFeasibilityDecisionSourceIndex): Promise<void>;
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { DESIGN_RESOURCE_SUBSTRATE_OBSERVATION_KINDS, } from "./design-resource-implementation-feasibility-types.js";
|
|
2
|
+
import { validateFeasibilityCells } from "./design-resource-implementation-feasibility-validation-cells.js";
|
|
3
|
+
import { assertSameSet, invalidFeasibility, requireKnownRefs, unique, } from "./design-resource-implementation-feasibility-validation-support.js";
|
|
4
|
+
import { createSymbolicDenotationCompilationSession } from "./symbolic-denotation-engine.js";
|
|
5
|
+
import { validateNoExactVisualValueCarriers } from "./design-resource-implementation-feasibility-validation-support.js";
|
|
6
|
+
import { assertProtectedRepositoryDirectory, assertProtectedRepositoryPath, } from "./repository-path-safety.js";
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
const OBSERVATION_SOURCE_ROLES = {
|
|
9
|
+
platform: "technical_platform",
|
|
10
|
+
framework_runtime: "framework_runtime",
|
|
11
|
+
ui_system: "ui_system",
|
|
12
|
+
token_theming_adapter: "token_theming_adapter",
|
|
13
|
+
component_owner_roots: "component_owner",
|
|
14
|
+
route_owner_roots: "route_owner",
|
|
15
|
+
};
|
|
16
|
+
export async function validateFeasibilityDocument(repository, document, model, decisionSources) {
|
|
17
|
+
if (document.target_ref !== model.target_ref)
|
|
18
|
+
invalidFeasibility("document_target_mismatch", `${document.target_ref}:${model.target_ref}`);
|
|
19
|
+
if (document.realization_mode === "reference" &&
|
|
20
|
+
model.source_profile_kind !== "reference")
|
|
21
|
+
invalidFeasibility("reference_mode_formal_implementation_forbidden", model.target_ref);
|
|
22
|
+
if (document.realization_mode !== "reference" &&
|
|
23
|
+
model.source_profile_kind === "reference")
|
|
24
|
+
invalidFeasibility("reference_profile_feasibility_mode_invalid", model.target_ref);
|
|
25
|
+
const sources = new Map(document.source_records.map((item) => [item.key, item]));
|
|
26
|
+
validateNoExactVisualValueCarriers(document);
|
|
27
|
+
await validateObservations(repository, document, sources);
|
|
28
|
+
validateCandidateComponentOwnerRoots(document);
|
|
29
|
+
const profileRefs = validateConditionModel(document, model);
|
|
30
|
+
await validateFeasibilityCells(repository, document, model, profileRefs, sources, decisionSources);
|
|
31
|
+
}
|
|
32
|
+
async function validateObservations(repository, document, sources) {
|
|
33
|
+
unique(document.substrate_observations.map((item) => item.kind), "substrate_observation_kind_duplicate");
|
|
34
|
+
if (document.realization_mode !== "reference")
|
|
35
|
+
assertSameSet(document.substrate_observations.map((item) => item.kind), [...DESIGN_RESOURCE_SUBSTRATE_OBSERVATION_KINDS], "substrate_observation_kind_set_mismatch");
|
|
36
|
+
for (const observation of document.substrate_observations) {
|
|
37
|
+
unique(observation.source_record_refs, "substrate_observation_source_duplicate", observation.kind);
|
|
38
|
+
requireKnownRefs(observation.source_record_refs, sources, "substrate_observation_source_unknown", observation.kind);
|
|
39
|
+
if (observation.disposition === "observed") {
|
|
40
|
+
validateObservedSubstrate(observation, sources);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
if (observation.value !== null)
|
|
44
|
+
invalidFeasibility("unobserved_substrate_value_forbidden", observation.kind);
|
|
45
|
+
if (observation.reason === null)
|
|
46
|
+
invalidFeasibility("unobserved_substrate_reason_required", observation.kind);
|
|
47
|
+
}
|
|
48
|
+
validateObservationValue(observation, sources);
|
|
49
|
+
if (observation.value?.kind === "repository_paths")
|
|
50
|
+
for (const repositoryPath of observation.value.paths)
|
|
51
|
+
await (observation.kind === "component_owner_roots" ||
|
|
52
|
+
observation.kind === "route_owner_roots"
|
|
53
|
+
? assertProtectedRepositoryDirectory
|
|
54
|
+
: assertProtectedRepositoryPath)(repository, path.resolve(repository, ...repositoryPath.split("/")), `design_resource_feasibility_repository_path:${observation.kind}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function validateCandidateComponentOwnerRoots(document) {
|
|
58
|
+
if (!document.component_family_cells.some((cell) => cell.feasible_realizations.length > 0))
|
|
59
|
+
return;
|
|
60
|
+
const roots = document.substrate_observations.find((observation) => observation.kind === "component_owner_roots");
|
|
61
|
+
if (roots?.disposition !== "observed" ||
|
|
62
|
+
roots.value?.kind !== "repository_paths" ||
|
|
63
|
+
roots.value.paths.length === 0)
|
|
64
|
+
invalidFeasibility("candidate_component_owner_roots_required", document.target_ref);
|
|
65
|
+
}
|
|
66
|
+
function validateObservedSubstrate(observation, sources) {
|
|
67
|
+
if (!observation.value)
|
|
68
|
+
invalidFeasibility("observed_substrate_value_required", observation.kind);
|
|
69
|
+
if (observation.reason !== null)
|
|
70
|
+
invalidFeasibility("observed_substrate_reason_forbidden", observation.kind);
|
|
71
|
+
if (!observation.source_record_refs.length)
|
|
72
|
+
invalidFeasibility("observed_substrate_source_required", observation.kind);
|
|
73
|
+
const requiredRole = OBSERVATION_SOURCE_ROLES[observation.kind];
|
|
74
|
+
if (!observation.source_record_refs.some((ref) => sources.get(ref).roles.includes(requiredRole)))
|
|
75
|
+
invalidFeasibility("observed_substrate_source_role_missing", `${observation.kind}:${requiredRole}`);
|
|
76
|
+
}
|
|
77
|
+
function validateObservationValue(observation, sources) {
|
|
78
|
+
if (!observation.value)
|
|
79
|
+
return;
|
|
80
|
+
if (["platform", "framework_runtime", "ui_system"].includes(observation.kind) &&
|
|
81
|
+
observation.value.kind !== "identifier")
|
|
82
|
+
invalidFeasibility("observation_value_kind_invalid", `${observation.kind}:${observation.value.kind}`);
|
|
83
|
+
if (["component_owner_roots", "route_owner_roots"].includes(observation.kind) &&
|
|
84
|
+
observation.value.kind !== "repository_paths")
|
|
85
|
+
invalidFeasibility("observation_value_kind_invalid", `${observation.kind}:${observation.value.kind}`);
|
|
86
|
+
if (observation.value?.kind === "identifier") {
|
|
87
|
+
const versionRef = observation.value.version_source_ref;
|
|
88
|
+
if (versionRef && !sources.has(versionRef))
|
|
89
|
+
invalidFeasibility("observation_version_source_unknown", versionRef);
|
|
90
|
+
}
|
|
91
|
+
else if (observation.value?.kind === "repository_paths" &&
|
|
92
|
+
!observation.value.paths.length) {
|
|
93
|
+
invalidFeasibility("observation_repository_paths_required", observation.kind);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function validateConditionModel(document, model) {
|
|
97
|
+
const conditionModel = document.condition_model;
|
|
98
|
+
if (model.representation === "fact_cells_v1" &&
|
|
99
|
+
conditionModel.kind !== "explicit_conditions_v1")
|
|
100
|
+
invalidFeasibility("v1_explicit_condition_model_required", model.target_ref);
|
|
101
|
+
if (model.representation === "symbolic_rules_v2" &&
|
|
102
|
+
conditionModel.kind !== "symbolic_regions_v2")
|
|
103
|
+
invalidFeasibility("v2_symbolic_condition_model_required", model.target_ref);
|
|
104
|
+
if (!conditionModel.profiles.length &&
|
|
105
|
+
document.realization_mode !== "reference")
|
|
106
|
+
invalidFeasibility("condition_profiles_required", model.target_ref);
|
|
107
|
+
unique(conditionModel.profiles.map((item) => item.key), "condition_profile_key_duplicate");
|
|
108
|
+
if (model.representation === "fact_cells_v1" &&
|
|
109
|
+
conditionModel.kind === "explicit_conditions_v1")
|
|
110
|
+
validateExplicitConditionProfiles(document, model);
|
|
111
|
+
if (model.representation === "symbolic_rules_v2" &&
|
|
112
|
+
conditionModel.kind === "symbolic_regions_v2" &&
|
|
113
|
+
conditionModel.profiles.length)
|
|
114
|
+
validateSymbolicConditionProfiles(document, model);
|
|
115
|
+
return new Set(conditionModel.profiles.map((item) => item.key));
|
|
116
|
+
}
|
|
117
|
+
function validateExplicitConditionProfiles(document, model) {
|
|
118
|
+
if (document.condition_model.kind !== "explicit_conditions_v1")
|
|
119
|
+
return;
|
|
120
|
+
const conditionRefs = document.condition_model.profiles.flatMap((profile) => {
|
|
121
|
+
if (!profile.condition_refs.length)
|
|
122
|
+
invalidFeasibility("condition_profile_empty", profile.key);
|
|
123
|
+
unique(profile.condition_refs, "condition_profile_ref_duplicate", profile.key);
|
|
124
|
+
return profile.condition_refs;
|
|
125
|
+
});
|
|
126
|
+
unique(conditionRefs, "condition_profile_overlap");
|
|
127
|
+
if (document.realization_mode !== "reference")
|
|
128
|
+
assertSameSet(conditionRefs, model.condition_refs, "condition_profile_set_mismatch");
|
|
129
|
+
}
|
|
130
|
+
function validateSymbolicConditionProfiles(document, model) {
|
|
131
|
+
if (document.condition_model.kind !== "symbolic_regions_v2")
|
|
132
|
+
return;
|
|
133
|
+
const profiles = document.condition_model.profiles;
|
|
134
|
+
const compilation = createSymbolicDenotationCompilationSession(model.axis_domains, [model.reachable_region, ...profiles.map((item) => item.region)]);
|
|
135
|
+
const reachable = compilation.compile(model.reachable_region);
|
|
136
|
+
for (const profile of profiles) {
|
|
137
|
+
const outside = compilation.compile({
|
|
138
|
+
op: "all",
|
|
139
|
+
predicates: [
|
|
140
|
+
profile.region,
|
|
141
|
+
{ op: "not", predicate: model.reachable_region },
|
|
142
|
+
],
|
|
143
|
+
});
|
|
144
|
+
if (outside.canonical_dag.root_ref !== "terminal.false")
|
|
145
|
+
invalidFeasibility("symbolic_condition_profile_unreachable", profile.key);
|
|
146
|
+
}
|
|
147
|
+
validateSymbolicProfileDisjointness(profiles, compilation);
|
|
148
|
+
if (document.realization_mode !== "reference") {
|
|
149
|
+
const union = compilation.compile({
|
|
150
|
+
op: "any",
|
|
151
|
+
predicates: profiles.map((item) => item.region),
|
|
152
|
+
});
|
|
153
|
+
if (union.canonical_sha256 !== reachable.canonical_sha256)
|
|
154
|
+
invalidFeasibility("symbolic_condition_profile_coverage_gap", model.target_ref);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
function validateSymbolicProfileDisjointness(profiles, compilation) {
|
|
158
|
+
for (let left = 0; left < profiles.length; left += 1)
|
|
159
|
+
for (let right = left + 1; right < profiles.length; right += 1) {
|
|
160
|
+
const overlap = compilation.compile({
|
|
161
|
+
op: "all",
|
|
162
|
+
predicates: [profiles[left].region, profiles[right].region],
|
|
163
|
+
});
|
|
164
|
+
if (overlap.canonical_dag.root_ref !== "terminal.false")
|
|
165
|
+
invalidFeasibility("symbolic_condition_profile_overlap", `${profiles[left].key}:${profiles[right].key}`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { DesignResourceImplementationFeasibilityCellV1, DesignResourceImplementationFeasibilityV1 } from "./design-resource-implementation-feasibility-types.js";
|
|
2
|
+
import type { DesignResourceImplementationFeasibilityTargetModel } from "./design-resource-implementation-feasibility-model.js";
|
|
3
|
+
export declare function validateDesignFactRefs(cell: DesignResourceImplementationFeasibilityCellV1, model: DesignResourceImplementationFeasibilityTargetModel, document: DesignResourceImplementationFeasibilityV1): void;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { assertSameSet, invalidFeasibility, } from "./design-resource-implementation-feasibility-validation-support.js";
|
|
2
|
+
import { createSymbolicDenotationCompilationSession } from "./symbolic-denotation-engine.js";
|
|
3
|
+
export function validateDesignFactRefs(cell, model, document) {
|
|
4
|
+
if (model.representation === "fact_cells_v1") {
|
|
5
|
+
validateV1FactRefs(cell, model, document);
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
8
|
+
validateV2RuleRefs(cell, model, document);
|
|
9
|
+
}
|
|
10
|
+
function validateV1FactRefs(cell, model, document) {
|
|
11
|
+
if (document.condition_model.kind !== "explicit_conditions_v1")
|
|
12
|
+
invalidFeasibility("v1_explicit_condition_model_required", cell.key);
|
|
13
|
+
const profile = document.condition_model.profiles.find((item) => item.key === cell.condition_profile_ref);
|
|
14
|
+
for (const ref of cell.design_fact_refs) {
|
|
15
|
+
const fact = model.facts.get(ref);
|
|
16
|
+
if (!fact)
|
|
17
|
+
invalidFeasibility("cell_design_fact_unknown", `${cell.key}:${ref}`);
|
|
18
|
+
if (fact.target_ref !== cell.target_ref ||
|
|
19
|
+
!model.component_family_subject_refs
|
|
20
|
+
.get(cell.component_family_ref)
|
|
21
|
+
.has(fact.subject_ref) ||
|
|
22
|
+
!profile.condition_refs.includes(fact.condition_ref))
|
|
23
|
+
invalidFeasibility("cell_design_fact_scope_mismatch", `${cell.key}:${ref}`);
|
|
24
|
+
}
|
|
25
|
+
const expectedRefs = [...model.facts.entries()]
|
|
26
|
+
.filter(([, fact]) => fact.target_ref === cell.target_ref &&
|
|
27
|
+
model.component_family_subject_refs
|
|
28
|
+
.get(cell.component_family_ref)
|
|
29
|
+
.has(fact.subject_ref) &&
|
|
30
|
+
profile.condition_refs.includes(fact.condition_ref))
|
|
31
|
+
.map(([ref]) => ref);
|
|
32
|
+
assertSameSet(cell.design_fact_refs, expectedRefs, "cell_design_fact_set_mismatch");
|
|
33
|
+
}
|
|
34
|
+
function validateV2RuleRefs(cell, model, document) {
|
|
35
|
+
if (document.condition_model.kind !== "symbolic_regions_v2")
|
|
36
|
+
invalidFeasibility("v2_symbolic_condition_model_required", cell.key);
|
|
37
|
+
const profile = document.condition_model.profiles.find((item) => item.key === cell.condition_profile_ref);
|
|
38
|
+
const referencedRules = cell.design_fact_refs.map((ref) => {
|
|
39
|
+
const rule = model.fact_rules.get(ref);
|
|
40
|
+
if (!rule)
|
|
41
|
+
invalidFeasibility("cell_design_rule_unknown", `${cell.key}:${ref}`);
|
|
42
|
+
return rule;
|
|
43
|
+
});
|
|
44
|
+
const familyRules = [...model.fact_rules.values()].filter((rule) => rule.target_ref === cell.target_ref &&
|
|
45
|
+
model.component_family_subject_refs
|
|
46
|
+
.get(cell.component_family_ref)
|
|
47
|
+
.has(rule.subject_or_relation_ref));
|
|
48
|
+
const compilation = createSymbolicDenotationCompilationSession(model.axis_domains, [
|
|
49
|
+
model.reachable_region,
|
|
50
|
+
profile.region,
|
|
51
|
+
...familyRules.map((rule) => rule.region),
|
|
52
|
+
]);
|
|
53
|
+
for (const rule of referencedRules) {
|
|
54
|
+
if (rule.target_ref !== cell.target_ref ||
|
|
55
|
+
!model.component_family_subject_refs
|
|
56
|
+
.get(cell.component_family_ref)
|
|
57
|
+
.has(rule.subject_or_relation_ref))
|
|
58
|
+
invalidFeasibility("cell_design_rule_scope_mismatch", `${cell.key}:${rule.key}`);
|
|
59
|
+
const intersection = compilation.compile({
|
|
60
|
+
op: "all",
|
|
61
|
+
predicates: [profile.region, rule.region],
|
|
62
|
+
});
|
|
63
|
+
if (intersection.canonical_dag.root_ref === "terminal.false")
|
|
64
|
+
invalidFeasibility("cell_design_rule_condition_mismatch", `${cell.key}:${rule.key}`);
|
|
65
|
+
}
|
|
66
|
+
const expectedRefs = familyRules
|
|
67
|
+
.filter((rule) => {
|
|
68
|
+
const intersection = compilation.compile({
|
|
69
|
+
op: "all",
|
|
70
|
+
predicates: [profile.region, rule.region],
|
|
71
|
+
});
|
|
72
|
+
return intersection.canonical_dag.root_ref !== "terminal.false";
|
|
73
|
+
})
|
|
74
|
+
.map((rule) => rule.key);
|
|
75
|
+
assertSameSet(cell.design_fact_refs, expectedRefs, "cell_design_rule_set_mismatch");
|
|
76
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { DesignResourceFeasibleRealizationV1, DesignResourceImplementationFeasibilityCellV1, DesignResourceTechnicalSourceRecordV1 } from "./design-resource-implementation-feasibility-types.js";
|
|
2
|
+
import { type DesignResourceFeasibilityDecisionSourceIndex } from "./design-resource-implementation-feasibility-source-decision.js";
|
|
3
|
+
export declare function validateFeasibleRealization(repository: string, realization: DesignResourceFeasibleRealizationV1, sources: Map<string, DesignResourceTechnicalSourceRecordV1>, decisionSources: DesignResourceFeasibilityDecisionSourceIndex, componentOwnerRoots: string[], scope: {
|
|
4
|
+
target_ref: string;
|
|
5
|
+
component_family_ref: string;
|
|
6
|
+
condition_scope_sha256: string;
|
|
7
|
+
}): Promise<void>;
|
|
8
|
+
export declare function validateRequiredRealization(cell: DesignResourceImplementationFeasibilityCellV1, sources: Map<string, DesignResourceTechnicalSourceRecordV1>, decisionSources: DesignResourceFeasibilityDecisionSourceIndex, conditionScopeSha256: string): void;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { invalidFeasibility, requireAtLeastOneSourceRole, requireKnownRefs, requireSourceRole, unique, } from "./design-resource-implementation-feasibility-validation-support.js";
|
|
3
|
+
import { assertProtectedRepositoryFile } from "./long-task-protected-files.js";
|
|
4
|
+
import { DESIGN_RESOURCE_FEASIBILITY_DECISION_SCHEMA, requireExactFeasibilityDecisionProjection, } from "./design-resource-implementation-feasibility-source-decision.js";
|
|
5
|
+
export async function validateFeasibleRealization(repository, realization, sources, decisionSources, componentOwnerRoots, scope) {
|
|
6
|
+
if (!realization.strategy_steps.length)
|
|
7
|
+
invalidFeasibility("realization_strategy_steps_required", realization.key);
|
|
8
|
+
unique(realization.strategy_steps, "realization_strategy_step_duplicate", realization.key);
|
|
9
|
+
if (!realization.primitive_refs.length)
|
|
10
|
+
invalidFeasibility("realization_primitive_refs_required", realization.key);
|
|
11
|
+
unique(realization.primitive_refs, "realization_primitive_ref_duplicate", realization.key);
|
|
12
|
+
if (!realization.owner_candidates.length)
|
|
13
|
+
invalidFeasibility("realization_owner_candidates_required", realization.key);
|
|
14
|
+
unique(realization.owner_candidates.map((item) => `${item.kind}:${item.locator}`), "realization_owner_candidate_duplicate", realization.key);
|
|
15
|
+
unique(realization.supported_customization_surfaces, "realization_customization_surface_duplicate", realization.key);
|
|
16
|
+
validateFeasibilityBasis(realization, sources);
|
|
17
|
+
unique(realization.observed_costs, "realization_observed_cost_duplicate", realization.key);
|
|
18
|
+
unique(realization.observed_risks, "realization_observed_risk_duplicate", realization.key);
|
|
19
|
+
for (const owner of realization.owner_candidates)
|
|
20
|
+
await validateOwnerCandidate(repository, realization.key, owner, sources, decisionSources, componentOwnerRoots, scope);
|
|
21
|
+
}
|
|
22
|
+
function validateFeasibilityBasis(realization, sources) {
|
|
23
|
+
if (!realization.feasibility_basis_refs.length)
|
|
24
|
+
invalidFeasibility("realization_feasibility_basis_required", realization.key);
|
|
25
|
+
requireKnownRefs(realization.feasibility_basis_refs, sources, "realization_feasibility_basis_unknown", realization.key);
|
|
26
|
+
unique(realization.feasibility_basis_refs, "realization_feasibility_basis_duplicate", realization.key);
|
|
27
|
+
requireAtLeastOneSourceRole(realization.feasibility_basis_refs, sources, "feasibility_basis", "realization_feasibility_basis_role_missing", realization.key);
|
|
28
|
+
requireAtLeastOneSourceRole(realization.feasibility_basis_refs, sources, "capability_basis", "realization_capability_basis_role_missing", realization.key);
|
|
29
|
+
}
|
|
30
|
+
async function validateOwnerCandidate(repository, realizationKey, owner, sources, decisionSources, componentOwnerRoots, scope) {
|
|
31
|
+
if (owner.kind === "existing_path") {
|
|
32
|
+
await assertProtectedRepositoryFile(repository, path.resolve(repository, ...owner.locator.split("/")), `design_resource_feasibility_owner:${realizationKey}`);
|
|
33
|
+
if (componentOwnerRoots.length > 0 &&
|
|
34
|
+
!componentOwnerRoots.some((root) => owner.locator === root || owner.locator.startsWith(`${root}/`)))
|
|
35
|
+
invalidFeasibility("existing_owner_outside_component_roots", `${realizationKey}:${owner.locator}`);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (!owner.authorization_source_refs.length)
|
|
39
|
+
invalidFeasibility("planned_owner_authorization_required", realizationKey);
|
|
40
|
+
unique(owner.authorization_source_refs, "planned_owner_authorization_duplicate", realizationKey);
|
|
41
|
+
requireSourceRole(owner.authorization_source_refs, sources, "planned_owner_authorization", "planned_owner_authorization_invalid", realizationKey);
|
|
42
|
+
requireExactFeasibilityDecisionProjection(owner.authorization_source_refs, decisionSources, {
|
|
43
|
+
schema_version: DESIGN_RESOURCE_FEASIBILITY_DECISION_SCHEMA,
|
|
44
|
+
mode: "planned_owner_authorization",
|
|
45
|
+
...scope,
|
|
46
|
+
owner_locator: owner.locator,
|
|
47
|
+
}, `planned_owner:${realizationKey}:${owner.locator}`, {
|
|
48
|
+
allReferencesMustBeSourceItems: true,
|
|
49
|
+
allowedItemKinds: ["technical_obligation"],
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
export function validateRequiredRealization(cell, sources, decisionSources, conditionScopeSha256) {
|
|
53
|
+
const required = cell.required_realization;
|
|
54
|
+
unique(required.technical_authority_source_refs, "required_realization_authority_duplicate", cell.key);
|
|
55
|
+
if (required.realization_ref === null) {
|
|
56
|
+
if (required.technical_authority_source_refs.length)
|
|
57
|
+
invalidFeasibility("required_realization_authority_without_selection", cell.key);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if (!cell.feasible_realizations.some((realization) => realization.key === required.realization_ref))
|
|
61
|
+
invalidFeasibility("required_realization_unknown", cell.key);
|
|
62
|
+
if (!required.technical_authority_source_refs.length)
|
|
63
|
+
invalidFeasibility("required_realization_authority_required", cell.key);
|
|
64
|
+
requireSourceRole(required.technical_authority_source_refs, sources, "technical_authority", "required_realization_authority_invalid", cell.key);
|
|
65
|
+
requireExactFeasibilityDecisionProjection(required.technical_authority_source_refs, decisionSources, {
|
|
66
|
+
schema_version: DESIGN_RESOURCE_FEASIBILITY_DECISION_SCHEMA,
|
|
67
|
+
mode: "required_realization",
|
|
68
|
+
target_ref: cell.target_ref,
|
|
69
|
+
component_family_ref: cell.component_family_ref,
|
|
70
|
+
condition_scope_sha256: conditionScopeSha256,
|
|
71
|
+
realization_ref: required.realization_ref,
|
|
72
|
+
}, `required_realization:${cell.key}`, {
|
|
73
|
+
allReferencesMustBeSourceItems: true,
|
|
74
|
+
allowedItemKinds: ["technical_obligation"],
|
|
75
|
+
});
|
|
76
|
+
}
|
|
@@ -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[]>;
|