feat(javascript): report observed export property presence (#1160)

* feat(javascript): report observed export property presence

Extend compare_javascript_export_shapes so each retained return variant
lists observed property names and each change reports presence independently
of value resolution. Complete parent coverage classifies one-sided names as
added or removed even when static values stay unknown.

Fixes #725

* test(javascript): match unknown export-shape values by availability

Nested availability objects include a reason when values stay unresolved.
Assert availability through objectContaining so presence-only added and
removed rows still verify unknown values.

* fix(javascript): preserve uncertain export property presence and locations

* fix(javascript): normalize presence and preserve local property coverage

* fix(javascript): require present discriminants for return pairing

* fix(javascript): normalize retained shapes before comparison

* refactor(javascript): share return projection with executable examples

* fix(javascript): localize uncertainty for missing mutated slots

* fix(javascript): bind advertised export examples to exact artifacts

* fix(javascript): keep uncertain property flow as candidates

---------

Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
This commit is contained in:
Matt Van Hornandmorluto authored and GitHub committed 2026-10-09 18:30:31 +08:00
1 parent 04aef6df33
commit 45e3edc17f
25 files changed
+1552 -113

No files matched your search

@@ -20,23 +20,16 @@ export const invalidateSemanticMutationPath = (
property.name === name
? {
...property,
...(remaining.length === 0
? { presence: "unknown-coverage" as const }
: {}),
value: invalidateSemanticMutationPath(property.value, remaining),
}
: property,
);
return value.unknownProperties || !observed
? {
status: "object",
properties,
unknownProperties: true,
omittedProperties: observed ? value.omittedProperties : null,
}
: {
status: "object",
properties,
unknownProperties: false,
omittedProperties: 0,
};
if (!observed)
properties.push({ name, value: unknown, presence: "unknown-coverage" });
return { ...value, properties };
}
if (value.status === "array") {
const index = typeof key === "number" ? key : Number(key);
@@ -46,20 +39,18 @@ export const invalidateSemanticMutationPath = (
String(index) !== String(key)
)
return unknown;
const observed = value.items[index] !== undefined;
const items = value.items.map((item, position) =>
position === index
? invalidateSemanticMutationPath(item, remaining)
: item,
);
return value.unknownItems || !observed
? {
status: "array",
items,
unknownItems: true,
omittedItems: observed ? value.omittedItems : null,
}
: { status: "array", items, unknownItems: false, omittedItems: 0 };
const itemPresence = {
...value.itemPresence,
...(remaining.length === 0 || value.items[index] === undefined
? { [index]: "unknown-coverage" as const }
: {}),
};
return { ...value, items, itemPresence };
}
return unknown;
};