fix(lease): restore uniform settings array replacement
AMD1213-B1: preserve the gated Claude hook composition explicitly in the lease overlay while restoring last-layer-wins arrays and null tombstones.
This commit is contained in:
@@ -253,12 +253,9 @@ function cloneValue(value: unknown): unknown {
|
||||
return value;
|
||||
}
|
||||
|
||||
type MergeContext = 'root' | 'hooks' | 'nested';
|
||||
|
||||
function mergeObject(
|
||||
lower: Record<string, unknown>,
|
||||
higher: Record<string, unknown>,
|
||||
context: MergeContext = 'nested',
|
||||
): Record<string, unknown> {
|
||||
const result = cloneValue(lower) as Record<string, unknown>;
|
||||
for (const [key, highValue] of Object.entries(higher)) {
|
||||
@@ -267,36 +264,23 @@ function mergeObject(
|
||||
continue;
|
||||
}
|
||||
const lowValue = result[key];
|
||||
if (context === 'hooks' && Array.isArray(lowValue) && Array.isArray(highValue)) {
|
||||
result[key] = [...(lowValue as unknown[]), ...(cloneValue(highValue) as unknown[])];
|
||||
continue;
|
||||
}
|
||||
result[key] =
|
||||
isPlainObject(lowValue) && isPlainObject(highValue)
|
||||
? mergeObject(
|
||||
lowValue,
|
||||
highValue,
|
||||
context === 'root' && key === 'hooks' ? 'hooks' : 'nested',
|
||||
)
|
||||
? mergeObject(lowValue, highValue)
|
||||
: cloneValue(highValue);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deep object merge. Scalars and arrays replace; null in a higher layer
|
||||
* deletes. Exception: hook event arrays directly under the top-level `hooks`
|
||||
* key concatenate (base entries first), so an overlay ADDS gating without
|
||||
* erasing the base QA hooks that share an event — replacing them would make
|
||||
* the gap-7 base/overlay split unimplementable without duplicating base
|
||||
* hooks inside the lease overlay. Removing an event entirely still works via
|
||||
* the null tombstone.
|
||||
* Deep object merge. Objects merge recursively; scalar and array conflicts
|
||||
* resolve last-layer-wins; null in a higher layer deletes the key.
|
||||
*/
|
||||
export function deepMergeSettings(
|
||||
...layers: ReadonlyArray<Record<string, unknown> | undefined>
|
||||
): Record<string, unknown> {
|
||||
return layers.reduce<Record<string, unknown>>(
|
||||
(merged, layer) => (layer === undefined ? merged : mergeObject(merged, layer, 'root')),
|
||||
(merged, layer) => (layer === undefined ? merged : mergeObject(merged, layer)),
|
||||
{},
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user